但願讀過本篇文章,你在看Webpack配置的時候,能在腦中造成Chunk的生成過程。css
Chunk不一樣於entry、 output、module這樣的概念,它們對應着Webpack配置對象中的一個字段,Chunk沒有單獨的配置字段,可是這個詞出如今CommonsChunkPlugin(Webpack3之前)、optimization.splitChunks(Webpack4之後)這樣的名稱之中。vue
Chunk是咱們理解Webpack,必須理解的一個概念。node
Chunk在Webpack裏指一個代碼塊,那具體是指什麼樣的代碼塊呢?react
首先來講module,Webpack能夠看作是模塊打包機,咱們編寫的任何文件,對於Webpack來講,都是一個個模塊。因此Webpack的配置文件,有一個module字段,module下有一個rules字段,rules下有就是處理模塊的規則,配置哪類的模塊,交由哪類loader來處理。webpack
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader"
}
]
},
...
]
},
複製代碼
Chunk是Webpack打包過程當中,一堆module的集合。咱們知道Webpack的打包是從一個入口文件開始,也能夠說是入口模塊,入口模塊引用這其餘模塊,模塊再引用模塊。Webpack經過引用關係逐個打包模塊,這些module就造成了一個Chunk。web
若是咱們有多個入口文件,可能會產出多條打包路徑,一條路徑就會造成一個Chunk。出了入口entry會產生Chunk,還有兩種途徑,下面會有介紹。數組
一般咱們會弄混這兩個概念,覺得Chunk就是Bundle,Bundle就是咱們最終輸出的一個或多個打包文件。確實,大多數狀況下,一個Chunk會生產一個Bundle。但有時候也不徹底是一對一的關係,好比咱們把 devtool配置成'source-map'。而後只有一個入口文件,也不配置代碼分割:瀏覽器
// webpack配置
entry: {
main: __dirname + "/app/main.js",
},
output: {
path: __dirname + "/public",//打包後的文件存放的地方
filename: "[name].js", //打包後輸出文件的文件名
},
devtool: 'source-map',
複製代碼
這樣的配置,會產生一個Chunk,可是會產生兩個bundle,以下圖 bash
這就是Chunk和Bundle的區別,Chunk是過程當中的代碼塊,Bundle是結果的代碼塊。app
查看Webpack源碼,發現有一個Chunk.js,點進去看:
/**
* A Chunk is a unit of encapsulation for Modules.
* Chunks are "rendered" into bundles that get emitted when the build completes.
*/
class Chunk {
}
複製代碼
裏面有一個Chunk類,這說明類Webpack在運行中,會生成Chunk對象,也能證實Chunk是過程當中的代碼塊。
Chunk類上面的兩句註釋:一個Chunk是一些模塊的封裝單元。Chunk在構建完成就呈現爲bundle。
entry的配置有三種方式:
entry: './src/js/main.js',
複製代碼
這種狀況只會產生一個Chunk。(這裏只說entry對Chunk的影響,不涉及代碼分割)
entry: ['./src/js/main.js','./src/js/other.js'],
複製代碼
這種狀況也只會產生一個Chunk。Webpack會將數組裏的源代碼,最終都打包到一個Bundle裏,緣由就是隻生成了一個Chunk.
entry: {
main: './src/js/main.js',
other: './src/js/other.js'
},
output: {
// path: __dirname + "/public",
// filename:'bundle.js'
// 以上2行會報錯
path: __dirname + "/public",//打包後的文件存放的地方
filename: "[name].js", //打包後輸出文件的文件名
}
複製代碼
對象中一個字段就會產生一個Chunk,因此在output中filename直接寫死名稱,會報錯。由於上面的配置,產生了兩個Chunk,最終會生成兩個Bundle,一個名稱確定不夠用了。須要用[name]變量來利用entry下的字段名稱,做爲生成Bundle們的名稱。
這裏面entry的key,也被用來看成它對應的Chunk的名稱,上面傳遞一個字符串和傳遞數組兩種方式,沒有key,也會默認給生成的Chunk一個main的名稱。
除了入口文件會影響Chunk,異步加載的模塊,也須要生成Chunk。
{
entry: {
"index": "pages/index.jsx"
},
output: {
filename: "[name].min.js",
chunkFilename: "[name].min.js"
}
}
const myModel = r => require.ensure([], () => r(require('./myVue.vue')), 'myModel')
複製代碼
這個時候chunkFilename字段就派上用場了,爲異步加載的Chunk命名。
咱們來分析一下,下面代碼會產生幾個Chunk,其中main.js文件和two.js文件,都引用了同一個greeter.js文件。main.js中使用了react。
module.exports = {
entry: {
main: __dirname + "/app/main.js",
other: __dirname + "/app/two.js",
},
output: {
path: __dirname + "/public",//打包後的文件存放的地方
filename: "[name].js", //打包後輸出文件的文件名
chunkFilename: '[name].js',
},
optimization: {
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
},
}
}
}
複製代碼
答案是5個,兩個入口分別產生一個, runtimeChunk: "single"會將Webpack在瀏覽器端運行時須要的代碼單獨抽離到一個文件,commons下的配置會產生一個Chunk,vendor下的配置會產生一個Chunk。以下圖。
今天的研究就到這裏。
可以在看Webpack的配置的時候,分辨出這樣的配置能生成幾個Chunk,Webpack就算是入門了,後面理解它的其餘概念,會容易不少。