偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Webpack 性能之使用 Cache 提升構(gòu)建性能

開(kāi)發(fā) 前端
經(jīng)過(guò)這么多年發(fā)展,Webpack 生態(tài)在前端工程化能力方面已經(jīng)發(fā)展的非常全面且強(qiáng)大,但大而全的背后其運(yùn)行性能卻逐漸為行業(yè)詬病,后進(jìn)如 Vite、SnowPack 等以性能著稱的同類框架更是在業(yè)內(nèi)掀起不小波瀾。

[[425963]]

不知不覺(jué),Webpack 原理系列已經(jīng)陸續(xù)出了十篇文章,以構(gòu)建主流程為綱逐步遞進(jìn)到插件、Loader、模塊、運(yùn)行時(shí)、Chunk、依賴對(duì)象、模塊依賴圖等關(guān)鍵概念的含義與運(yùn)行原理,再到 HMR、Tree-Shaking 等特性的功能介紹和原理解析,滿滿當(dāng)當(dāng)十篇文章,合計(jì)超過(guò) 5W 字,基本上已經(jīng)貫徹 Webpack 整個(gè)核心流程。

接下來(lái)我會(huì)繼續(xù)沿著 Webpack 這個(gè)少人問(wèn)津的方向,推出兩個(gè)實(shí)用性更強(qiáng)的系列:基礎(chǔ)應(yīng)用、性能優(yōu)化。性能優(yōu)化系列主要介紹在 Webpack 場(chǎng)景下如何通過(guò)配置、插件等手段,優(yōu)化構(gòu)建與運(yùn)行性能,以及這些性能優(yōu)化背后的核心原理,例如本文即將介紹的 Webpack5 全新的 cache 功能。

使用持久化緩存

經(jīng)過(guò)這么多年發(fā)展,Webpack 生態(tài)在前端工程化能力方面已經(jīng)發(fā)展的非常全面且強(qiáng)大,但大而全的背后其運(yùn)行性能卻逐漸為行業(yè)詬病,后進(jìn)如 Vite、SnowPack 等以性能著稱的同類框架更是在業(yè)內(nèi)掀起不小波瀾。為此,Webpack 終于在第 5 個(gè)大版本引入持久化緩存,提升運(yùn)行性能。

持久化緩存算得上是 Webpack 5 最令人振奮的特性之一,它能夠?qū)⑹状螛?gòu)建結(jié)果持久化到本地文件系統(tǒng),在下次執(zhí)行構(gòu)建時(shí)跳過(guò)一系列解析、鏈接、編譯等非常消耗性能的操作,直接復(fù)用 module、chunk 的構(gòu)建結(jié)果。

使用持久化緩存后,構(gòu)建性能有巨大提升!以 Three.js 為例,該項(xiàng)目包含 362 份 JS 文件,合計(jì)約 3w 行代碼,算得上中大型項(xiàng)目:

配置 babel-loader、eslint-loader 后,在我機(jī)器上測(cè)試,未使用 cache 特性時(shí)構(gòu)建耗時(shí)大約在 11000ms 到 18000ms 之間;啟動(dòng) cache 功能后第二次構(gòu)建耗時(shí)降低到 500ms 到 800ms 之間,兩者相差接近 「50」 倍!

而這接近 50 倍的性能提升,僅僅需要在 Webpack5 場(chǎng)景下設(shè)置 cache.type = 'filesystem' 即可開(kāi)啟:

  1. module.exports = { 
  2.     //... 
  3.     cache: { 
  4.         type: 'filesystem' 
  5.     }, 
  6.     //... 
  7. }; 

原理

那么,為什么開(kāi)啟持久化緩存之后構(gòu)建性能會(huì)有如此巨大的提升呢?一言蔽之,Webpack5 會(huì)將首次構(gòu)建出的 Module、Chunk、ModuleGraph 等對(duì)象序列化后保存到硬盤中,后面再運(yùn)行的時(shí)候就可以跳過(guò)一些耗時(shí)的編譯動(dòng)作,直接復(fù)用緩存信息。

構(gòu)建流程

在《Webpack 原理系列》中,我們已經(jīng)深入聊了很多關(guān)于 Webpack 構(gòu)建功能的運(yùn)行流程與實(shí)現(xiàn)細(xì)節(jié)的內(nèi)容,為了加深對(duì)緩存的理解,這里有必要從構(gòu)建性能角度簡(jiǎn)單回顧一下。

Webpack 的構(gòu)建過(guò)程大致上可劃分為三個(gè)階段:

初始化,主要是根據(jù)配置信息設(shè)置內(nèi)置的各類插件

Make - 構(gòu)建階段,從 entry 模塊開(kāi)始,執(zhí)行:

  • 讀入文件內(nèi)容
  • 調(diào)用 Loader 轉(zhuǎn)譯文件內(nèi)容
  • 調(diào)用 acorn 生成 AST 結(jié)構(gòu)
  • 分析 AST,確定模塊依賴列表
  • 遍歷模塊依賴列表,對(duì)每一個(gè)依賴模塊重新執(zhí)行上述流程,直到生成完整的模塊依賴圖 —— ModuleGraph 對(duì)象

Seal - 生成階段,過(guò)程:

  • 代碼轉(zhuǎn)譯,如 import 轉(zhuǎn)換為 require 調(diào)用
  • 分析運(yùn)行時(shí)依賴
  • 遍歷模塊依賴圖,對(duì)每一個(gè)模塊執(zhí)行:
  • 合并模塊代碼與運(yùn)行時(shí)代碼,生成 chunk
  • 執(zhí)行產(chǎn)物優(yōu)化操作,如 Tree-shaking
  • 將最終結(jié)果寫出到產(chǎn)物文件

過(guò)程中存在許多 CPU 密集型操作,例如調(diào)用 Loader 鏈加載文件時(shí),遇到 babel-loader、eslint-loader、ts-loader 等工具時(shí)可能需要重復(fù)生成 AST;分析模塊依賴信息時(shí)則需要遍歷 AST,執(zhí)行大量運(yùn)算;Seal 階段也同樣存在大量 AST 遍歷,以及代碼轉(zhuǎn)換、優(yōu)化操作,等等。

實(shí)現(xiàn)緩存

在引入持久化緩存之前,Webpack 在每次運(yùn)行時(shí)都需要對(duì)所有模塊完整執(zhí)行上述構(gòu)建流程,假設(shè)業(yè)務(wù)項(xiàng)目中有 1000 個(gè)文件,則每次執(zhí)行 npx webpack 命令時(shí)都需要從 0 開(kāi)始執(zhí)行 1000 次構(gòu)建、生成邏輯。

而 Webpack5 的持久化緩存功能則嘗試將構(gòu)建結(jié)果保存到文件系統(tǒng)中,在下次編譯時(shí)對(duì)比每一個(gè)文件的內(nèi)容哈?;驎r(shí)間戳,未發(fā)生變化的文件跳過(guò)編譯操作,直接使用緩存副本,減少重復(fù)計(jì)算;發(fā)生變更的模塊則重新執(zhí)行編譯流程。緩存執(zhí)行時(shí)機(jī)如下圖:

如圖,Webpack 在首次構(gòu)建完畢后將 Module、Chunk、ModuleGraph 三類對(duì)象的狀態(tài)序列化并記錄到緩存文件中;在下次構(gòu)建開(kāi)始時(shí),嘗試讀入并恢復(fù)這些對(duì)象的狀態(tài),從而跳過(guò)執(zhí)行 Loader 鏈、解析 AST、解析依賴等耗時(shí)操作,提升編譯性能。

用法詳解

理解緩存的核心原理后,我們?cè)倩剡^(guò)頭來(lái)看看 cache 提供的配置項(xiàng)列表,下面摘錄幾個(gè)比較常用的配置項(xiàng):

官方文檔:https://webpack.js.org/configuration/cache

  • cache.type:緩存類型,支持 'memory' | 'filesystem',需要設(shè)置 filesystem 才能開(kāi)啟持久緩存
  • cache.cacheDirectory:緩存文件存放的路徑,默認(rèn)為 node_modules/.cache/webpack
  • cache.buildDependencies:額外的依賴文件,當(dāng)這些文件內(nèi)容發(fā)生變化時(shí),緩存會(huì)完全失效而執(zhí)行完整的編譯構(gòu)建,通??稍O(shè)置為項(xiàng)目配置文件,如:
  1. module.exports = { 
  2.   cache: { 
  3.     buildDependencies: { 
  4.       config: [path.join(__dirname, 'webpack.dll_config.js')], 
  5.     }, 
  6.   }, 
  7. }; 
  • cache.managedPaths:受控目錄,Webpack 構(gòu)建時(shí)會(huì)跳過(guò)新舊代碼哈希值與時(shí)間戳的對(duì)比,直接使用緩存副本,默認(rèn)值為 ['./node_modules']
  • cache.profile:是否輸出緩存處理過(guò)程的詳細(xì)日志,默認(rèn)為 false
  • cache.maxAge:緩存失效時(shí)間,默認(rèn)值為 5184000000

使用時(shí)通常關(guān)注上述配置項(xiàng)即可,其它如 idleTimeout、idleTimeoutAfterLargeChanges 等項(xiàng)均與 Webpack 內(nèi)部實(shí)現(xiàn)算法有關(guān),與緩存效果關(guān)系不大,無(wú)需關(guān)注。

Webpack 4 中的緩存

實(shí)際上,Webpack 4 已經(jīng)內(nèi)置使用內(nèi)存實(shí)現(xiàn)的臨時(shí)緩存功能,但必須在 watch 模式下使用,進(jìn)程退出后立即失效,實(shí)用性不高。不過(guò),在 Webpack 4 及之前版本中可以使用一些 loader 自帶的緩存功能提升構(gòu)建性能,例如 babel-loader、eslint-loader、cache-loader 。

開(kāi)啟babel-loader緩存

只需設(shè)置 cacheDirectory = true 即可開(kāi)啟 babel-loader 持久化緩存功能,例如:

  1. module.exports = { 
  2.     // ... 
  3.     module: { 
  4.         rules: [{ 
  5.             test: /\.m?js$/, 
  6.             loader: 'babel-loader'
  7.             options: { 
  8.                 cacheDirectory: true
  9.             }, 
  10.         }] 
  11.     }, 
  12.     // ... 
  13. }; 

配置項(xiàng)說(shuō)明:https://github.com/babel/babel-loader#options

以 Three.js 為例,開(kāi)啟緩存后生產(chǎn)環(huán)境構(gòu)建耗時(shí)從 3500ms 降低到 1600ms;開(kāi)發(fā)環(huán)境構(gòu)建從 6400ms 降低到 4500ms,性能提升約 30% ~ 50% 。

默認(rèn)情況下,babel-loader 會(huì)將緩存內(nèi)容保存到 node_modules/.cache/babel-loader 目錄,用戶也可以通過(guò) cacheDirectory = 'dir' 方式設(shè)置緩存路徑。

開(kāi)啟eslint-loader緩存

eslint-loader 同樣支持緩存功能,只需設(shè)置 cache = true 即可開(kāi)啟,如:

  1. module.exports = { 
  2.     // ... 
  3.     module: { 
  4.         rules: [{ 
  5.             test: /\.js$/, 
  6.             exclude: /node_modules/, 
  7.             loader: 'eslint-loader'
  8.             options: { 
  9.                 cache: true
  10.             }, 
  11.         }, ] 
  12.     }, 
  13.     // ... 
  14. }; 

配置項(xiàng)說(shuō)明:https://github.com/webpack-contrib/eslint-loader#cache

依然以 Three.js 為例,開(kāi)啟緩存后生產(chǎn)環(huán)境構(gòu)建耗時(shí)從 6400ms 降低到 1400ms;開(kāi)發(fā)環(huán)境構(gòu)建從 7000ms 降低到 2100ms,性能提升達(dá)到 70% ~ 80%。

默認(rèn)情況下,babel-loader 會(huì)將緩存內(nèi)容保存到 ./node_modules/.cache/eslint-loader 目錄,用戶也可以通過(guò) cache = 'dir' 方式設(shè)置緩存路徑。

使用cache-loader

除 babel-loader、eslint-loader 這類特化 loader 自身攜帶的緩存功能外,Webpack 4 中還可以使用 cache-loader 實(shí)現(xiàn)與 Webpack 5 相似的通用持久化緩存功能,使用上只需將 cache-loader 配置在 loader 數(shù)組首位,例如:

  1. const path = require("path"); 
  2. const webpack = require("webpack"); 
  3.  
  4. module.exports = { 
  5.     // ... 
  6.     module: { 
  7.         rules: [{ 
  8.             test: /\.js$/, 
  9.             use: ['cache-loader''babel-loader''eslint-loader'
  10.         }] 
  11.     }, 
  12.     // ... 
  13. }; 

cache-loader 文檔:https://www.npmjs.com/package/cache-loader

使用 cache-loader 后,生產(chǎn)環(huán)境構(gòu)建耗時(shí)從 10602ms 降低到 1540ms;開(kāi)發(fā)環(huán)境構(gòu)建從 11130ms 降低到 4247ms,性能提升約 「60% ~ 80%」。

與 Webpack 5 自帶的持久化緩存不同,cache-loader 僅 Loader 執(zhí)行結(jié)果有效,緩存范圍與深度不如內(nèi)置的緩存功能,所以性能收益相對(duì)較低,但在 Webpack 4 版本下已經(jīng)不失為一種簡(jiǎn)單而有效的性能優(yōu)化手段。

總結(jié)

網(wǎng)絡(luò)上關(guān)于 Webpack 持久化緩存的討論特別少,但這確實(shí)是 Webpack 5 引入的一個(gè)特別讓人振奮的功能,甚至在某些情況下能夠讓構(gòu)建性能達(dá)到 Unbundle 方案的量級(jí),相信隨著 Webpack 5 的推廣覆蓋,持久化緩存會(huì)成為 Webpack 性能優(yōu)化的一大利器。

本文轉(zhuǎn)載自微信公眾號(hào)「Tecvan」

 

責(zé)任編輯:姜華 來(lái)源: Tecvan
相關(guān)推薦

2021-10-25 10:23:49

Webpack 前端Tree shakin

2023-08-03 08:06:50

2019-03-15 15:00:49

Webpack構(gòu)建速度前端

2025-06-18 11:16:50

大模型性能KV-Cache

2019-03-26 10:02:16

WebpackJavascript前端

2020-09-19 21:26:56

webpack

2021-11-15 09:44:49

Webpack 前端 Scope Hois

2009-08-05 15:13:32

使用Cache提高AS

2011-02-23 09:49:40

ASP.NET

2023-03-01 15:14:48

數(shù)據(jù)集機(jī)器學(xué)習(xí)

2023-05-12 13:21:12

JMHJava程序

2017-03-13 09:50:00

HadoopHive

2011-02-16 09:08:27

ASP.NET

2011-07-09 23:24:57

PHP

2011-02-15 09:31:56

ASP.NET

2021-07-04 22:22:23

Webpack5前端工具

2021-11-09 09:57:46

Webpack 前端分包優(yōu)化

2021-10-12 09:52:30

Webpack 前端多進(jìn)程打包

2019-03-05 10:20:49

WebWebpack分離數(shù)據(jù)

2015-01-06 09:59:03

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)