真香 - Webpack5 新特性之增量編譯
webpack作為最使用最廣泛的前端打包工具,已經(jīng)成為前端工程化基礎(chǔ)設(shè)施的一部分。
webpack5正式發(fā)布于2020年10月10號(hào),距離上一個(gè)大版本W(wǎng)ebpack4更新已經(jīng)是2年前年了,每個(gè)大版本的升級(jí)都會(huì)有相當(dāng)多的改變和提升,今天咱們就來看看增量編輯和長(zhǎng)期緩存。
增量編譯(官方稱作:優(yōu)化持久化緩存)
Webpack5之前在構(gòu)建時(shí),會(huì)以配置的 entry 為入口,遞歸解析模塊依賴,構(gòu)建出一個(gè)依賴圖(graph),該依賴圖記錄代碼中各個(gè) module 之間的關(guān)系。
ps: graph ?是什么?圖是一種數(shù)據(jù)結(jié)構(gòu),類似下面這樣

每當(dāng)有文件內(nèi)容更新的時(shí)候,會(huì)重新遞歸生成依賴圖,如果簡(jiǎn)單粗暴地重建依賴圖再編譯,會(huì)有很大的性能開銷。在webpack5中,利用緩存實(shí)現(xiàn)增量編譯,從而提升構(gòu)建性能。每當(dāng)代碼變化、模塊之間依賴關(guān)系改變導(dǎo)致依賴圖改變時(shí), Webpack 會(huì)讀取記錄做增量編譯。
緩存(內(nèi)存 / 磁盤兩種形式)中的主要內(nèi)容是 module objects,在編譯的時(shí)候會(huì)將依賴圖以二進(jìn)制或者 json 文件存儲(chǔ)在硬盤上。
之前持久緩存的方式
使用 cache-loader 可以將編譯結(jié)果寫入硬盤緩存,Webpack 再次構(gòu)建時(shí)如果文件沒有發(fā)生變化則會(huì)直接拉取緩存。 還有一部分 loader 自帶緩存配置,比如 babel-loader,可以配置參數(shù) cacheDirectory 使用緩存,將每次的編譯結(jié)果寫進(jìn)磁盤(默認(rèn)在 node_modules/.cache/babel-loader 目錄) terser-webpack-plugin 開啟緩存
webpack5持久緩存方式
v5 中緩存默認(rèn)是 memory,你可以修改設(shè)置寫入硬盤:
module.export={
????cache{
???????type:'filesystem',??//??'memory'?|?'filesystem'
????????cacheDirectory:?'node_modules/.cache/webpack',?//?默認(rèn)將緩存存儲(chǔ)在?node_modules/.cache/webpack
????????//?緩存依賴,當(dāng)緩存依賴修改時(shí),緩存失效
????????buildDependencies:{
?????????//?將你的配置添加依賴,更改配置時(shí),使得緩存失效
?????????config:?[__filename]
?????}?
????}
}
增量編譯體驗(yàn)
下面來嘗試下這個(gè)功能,并同時(shí)和webpack4做下對(duì)比

為了能夠看出對(duì)比效果,搞了一堆模塊,不過代碼量都很少。
配置環(huán)境 - webpack4 安裝
下面使用yarn 安裝,本人習(xí)慣用yarn,因?yàn)樗俣葔蚩?/p>
//?webpack4
?yarn?add?webpack@4?webpack-cli@3?babel-loader?@babel/core??@babel/preset-env?-D
const?path=require('path');?
module.exports={
????mode:"development",
????entry:{
????????index:'./src/pages/home/index.js'?//入口文件
????},
????output:{
????????filename:'[name].js',?
????????path:path.resolve(__dirname,'./dist')?//指定生成的文件目錄
????},
????//?模塊
???module:{
????rules:[
??????{
????????test:/\.js$/,
????????exclude:/node_modules/,
????????use:[
??????????{
????????????loader:'babel-loader',
????????????options:{
??????????????presets:[
????????????????'@babel/preset-env',
??????????????]
????????????},
??????????}
????????]
??????},
????]
??},
}
配置環(huán)境 - webpack5 安裝
//?webpack5
?yarn?add?webpack?webpack-cli?babel-loader?@babel/core??@babel/preset-env?-D
const?path=require('path');?、
module.exports={
????mode:"development",?、
????entry:{
????????index:'./src/pages/home/index.js'?、
????},
????output:{
????????filename:'[name].js',、
????????path:path.resolve(__dirname,'./dist')、
????},
????cache:?{
????????type:?'filesystem',//使用文件緩存
????????//?cacheDirectory?默認(rèn)路徑是?node_modules/.cache/webpack
????????cacheDirectory:?path.resolve(__dirname,?'./temp_cache')?//本地目錄
??????},
????//?模塊
???module:{
????rules:[
??????{
????????test:/\.js$/,
????????exclude:/node_modules/,
????????use:[
??????????{
????????????loader:'babel-loader',
????????????options:{
??????????????presets:[
????????????????'@babel/preset-env',
??????????????]
????????????},
??????????}
????????]
??????},
????]
??},
}
配置啟動(dòng)命令
??"scripts":?{
????"test":?"echo?\"Error:?no?test?specified\"?&&?exit?1",
????"start":?"webpack?--config?webpack.config.js"
??},
構(gòu)建結(jié)果對(duì)比
//執(zhí)行
yarn?start
首次編譯?v5??done?in?1.5s?左右??
首次編譯?v4??done?in?1.05s左????
后續(xù)無修改編譯:v5 done?in?0.6s?左右??
后續(xù)無修改編譯:v4 done?in?0.9s?左右
修改后編譯:v5 done?in?1.5s?左右??
修改后編譯:v4 done?in?1.5s?左右??
但v5里多了一個(gè)時(shí)間?webpack?compiled?successfully?time,這個(gè)在v4里默認(rèn)沒有顯示
V5?首次編譯???webpack?compiled?successfully?in?723?ms
V5?無修改編譯?webpack?compiled?successfully?in?100?ms
V5?修改后編譯?webpack?compiled?successfully?in?417?ms
但我們應(yīng)該以?done?in?time?作為對(duì)比
構(gòu)建產(chǎn)物和日志
v5 緩存文件

v5首次編譯

v5 無修改2次編譯
直接讀取緩存

v5修改后編譯
增量編譯,只編譯修改的模塊

v4 首次編譯

v4 無修改2次編譯
全量編譯

v4 修改后編譯
全量編譯

總結(jié)
模塊較少,代碼量少時(shí),增量編輯的優(yōu)勢(shì)并不明顯,甚至首次編譯的速度還會(huì)低于v4的速度,因?yàn)関5需要處理緩存。
增量編譯中:v5只編譯了修改的模塊,而v4每次編譯都是所有模塊重新編譯,全量執(zhí)行。
代碼量較少,性能提升不明顯,相信在復(fù)雜龐大的項(xiàng)目中會(huì)有更好的效果,因?yàn)樵隽烤幾g無疑會(huì)更節(jié)省cpu和內(nèi)存的使用率,后面試著把老項(xiàng)目升級(jí)下,看看最終的一個(gè)打包速度能提升多少。
今日一提就到這里,希望對(duì)你點(diǎn)幫助。
Webpack V5還有非常多的特性,比如長(zhǎng)期緩存、更智能的tree shaking、模塊聯(lián)邦 等,一起來探索吧。
點(diǎn)個(gè)『在看』支持下?
