前言
該筆記是基於居玉皓老師的《Webpack實戰:入門、進階與調優》與webpack官方文檔的內容記錄的
入口起點
資源處理流程
在一切流程的最開始,我們需要指定一個或多個入口(entry),也就是告訴Webpack具體從源碼目錄下的哪個文件開始打包。
如果把工程中各個模塊的依賴關系當作一棵樹,那么入口就是這棵依賴樹的根
這些存在依賴關系的模塊會在打包時被封裝為一個chunk。那chunk是什么呢?
chunk字面的意思是代碼塊,在Webpack中可以理解成被抽象和包裝過后的一些模塊。它就像一個裝着很多文件的文件袋,里面的文件就是各個模塊,Webpack在外面加了一層包裹,從而形成了chunk:
根據具體配置不同,一個工程打包時可能會產生一個或多個chunk。
工程中可以定義多個入口,每一個入口都會產生一個結果資源
比如我們工程中有兩個入口src/index.js
和src/lib.js
,在一般情形下會打包生成dist/index.js
和dist/lib.js
。
在一些特殊情況下,一個入口也可能產生多個chunk並最終生成多個bundle
單個入口文件
用法:entry:string|Array<string>
1、簡寫語法
webpack.config.js
//由於是單個,所以可以簡寫成:
module.exports = {
entry: './main.js'
};
上面的入口配置寫法其實是下面的簡寫
module.exports = {
entry: {
main: './main.js'
}
};
2、數組語法
module.exports = {
entry: {
main:['./main.js','./main2.js']
}
};
傳入一個數組的作用是將多個資源預先合並,在打包時Webpack會將數組中的最后一個元素作為實際的入口路徑
在使用字符串或數組定義單入口時,並沒有辦法更改chunk name,只能為默認的“main”。
多個入口文件
用法:entry: {[entryChunkName: string]: string|Array}
對象語法
module.exports = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
這會比較繁瑣。然而這是應用程序中定義入口的最可擴展的方式。
“可擴展的 webpack 配置”:可重用並且可以與其他配置組合使用。這是一種流行的技術,用於將關注點從環境(environment)、構建目標(build target)、運行時(runtime)中分離。然后使用專門的工具(如 webpack-merge)將它們合並。
應用場景
1、單頁應用
無論是框架、庫,還是各個頁面的模塊,都由app.js
單一的入口進行引用。這樣做的好處是只會產生一個JS文件,依賴關系清晰。
module.exports = {
entry: './src/app.js'
};
這種做法也有弊端,即所有模塊都打包到一起,當應用的規模上升到一定程度之后會導致產生的資源體積過大,降低用戶的頁面渲染速度
在Webpack默認配置中,當一個bundle大於250kB時(壓縮前)會認為這個bundle已經過大了,在打包時會發生警告,如圖:
2、分離第三方庫(vendor)
為解決上方的問題,可以提取第三方庫(vender)
vendor的意思是“供應商”,在Webpack中vendor一般指的是工程所使用的庫、框架等第三方模塊集中打包而產生的bundle
module.exports = {
entry: {
app: './src/app.js',
vendors: ['react','react-dom','react-router'],
}
};
基於但也應用的例子,我們添加了一個新的chunk name為vendor
的入口,並通過數組的形式把工程所依賴的第三方模塊放了進去
我們並沒有為vendor設置入口路徑,Webpack要如何打包呢?
這時我們可以使用CommonsChunkPlugin(在Webpack 4之后CommonsChunkPlugin已被廢棄,可以采用optimization.splitChunks)將app與vendor這兩個chunk中的公共模塊提取出來
通過這樣的配置,app.js產生的bundle將只包含業務模塊,其依賴的第三方模塊將會被抽取出來生成一個新的bundle,這也就達到了我們提取vendor的目標
由於vendor僅僅包含第三方模塊,這部分不會經常變動。因此可以有效地利用客戶端緩存,在用戶后續請求頁面時會加快整體的渲染速度。
CommonsChunkPlugin主要是用來提取第三方庫和公共模塊,避免首屏加載的bundle文件或者按需加載的bundle文件體積過大,從而導致加載時間過長。
3、多頁應用
對於多頁應用的場景,為了盡可能減小資源的體積,我們希望每個頁面都只加載各自必要的邏輯,而不是將所有頁面打包到同一個bundle中。因此每個頁面都需要有一個獨立的bundle,這種情形我們使用多入口來實現。請看下面的例子:
module.exports = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
上面的配置告訴webpack 需要 3 個獨立分離的依賴圖,此時入口與頁面是一一對應的,這樣每個HTML只要引入各自的JS就可以加載其所需要的模塊