從 webpack4 開始,用 SplitChunksPlugin 插件替換了 CommonsChunkPlugin 插件。 相對於 CommonsChunkPlugin ,SplitChunksPlugin 的使用更加方便和清晰。javascript
SplitChunksPlugin 是 webpack4 內置的開箱即用的代碼塊分離插件,webpack4 會根據你配置好 optimization.splitChunks 規則,進行代碼分割,打包成不一樣的代碼塊。這樣的好處在於避免代碼重複引用,減小代碼體積,按需加載,從而使瀏覽器資源加載速度快,而且減小服務器的壓力和帶寬。html
SplitChunksPlugin 文檔:www.webpackjs.com/plugins/spl…java
initial
、async
和 all
屬性優先級 minSize > maxSize > maxAsyncRequests > maxInitialRequestwebpack
這裏重要介紹一下 chunks 的三個屬性 initial
、async
和 all
。git
具體能夠參考這篇文章: Webpack 4 Mysterious SplitChunks Plugingithub
經過 html-webpack-plugin 自動生成 index.htmlweb
npm install -D html-webpack-plugin
npm install -D webpack // html-webpack-plugin 依賴於 webpack
複製代碼
// `--` 表明目錄, `-` 表明文件
--demo08
--src
-app1.js
-app2.js
-module1.js
-module2.js
-module3.js
-index.html
-webpack.config.js
複製代碼
src/module1.jsnpm
export const module1 = 'module1';
複製代碼
src/module2.js瀏覽器
export const module2 = 'module2';
複製代碼
src/module3.js緩存
export const module3 = 'module3';
複製代碼
src/app1.js
import { module1 } from './module1';
import { module2 } from './module2';
// module1 module2 屬於同步加載
console.log('app1: ', module1);
console.log('app1: ', module2);
// 經過require.ensure對module3.js進行加載調用(此寫法在ts模式支持)
setTimeout(() => {
require.ensure(
[],
function () {
const module3 = require("./module3");
console.log('app1: ', module3.module3);
},
"module3"
);
}, 3000);
// // 異步加載的另外一種寫法(此寫法在ts模式下不支持)
// setTimeout(() => {
// import(/* webpackChunkName: 'module3'*/ "./module3").then(function (module3) {
// console.log(module3.module3);
// });
// }, 3000);
複製代碼
src/app2.js
import { module1 } from './module1';
import { module2 } from './module2';
import { module3 } from './module3';
// module1 module2 module3 都屬於同步加載(注意對比app1.js)
console.log('app2: ', module1);
console.log('app2: ', module2);
console.log('app2: ', module3);
複製代碼
webpack.config.js
const path = require("path");
module.exports = {
mode: 'production' || 'development',
entry: {
app1: "./src/app1.js",
app2: "./src/app2.js"
},
output: {
publicPath: __dirname + "/dist/", // 打包後資源文件的引用會基於此路徑
path: path.resolve(__dirname, "dist"), // 打包後的輸出目錄
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js"
},
optimization: {
// runtimeChunk: "single", // 使用single模式,能夠避免每個包都包含webpack的運行文件
splitChunks: {
cacheGroups: {
modules: {
chunks: "async" || "initial" || "all", // 三選一
minChunks: 1, // 代碼塊至少被引用的次數
maxInitialRequests: 3, // 設置最大的請求數
minSize: 0, // 設置每一個chunk最小的大小,只有大於這個值,纔會被打包進一個chunk
automaticNameDelimiter: '~'
}
}
}
}
};
複製代碼
(默認你已經安裝了全局 webpack 以及 webpack-cli )
webpack
複製代碼
打包成功後,結果輸出在 demo08 的dist目錄下
在瀏覽器運行 dist/index.html,打開控制檯能夠觀察異步加載模塊的效果。
這裏能夠經過修改以上參數(好比 chunks
, minChunks
, minSize
)的值來查看不一樣的輸出結果。
如上 webpack.config.js 配置文件,設置 minSize
爲 0
,以及 minChunks
爲 1
以確保知足一個新塊的條件。
chunks
爲 async
時webpack只對異步加載的模塊進行分離,因此輸出結果爲:
app1.bundle.js
app2.bundle.js
modules~module3.chunk.js
複製代碼
(注意以上例子中有兩個入口文件 app1.js app2.js)
app1.js相關:
app1.bundle.js ( app1 主模塊,而且包含 module1.js 和 module2.js)
modules~module3.chunk.js
複製代碼
app2.js相關:
app2.bundle.js ( app2 主模塊,而且包含 module1.js、module2.js 和 module3.js)
複製代碼
chunks
爲 initial
時webpack對全部模塊進行分離,若是一個模塊既被異步引用,也被同部引用,那麼會生成兩個包,因此輸出結果爲:
app1.bundle.js
app2.bundle.js
module3.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2.chunk.js
複製代碼
app1.js相關:
app1.bundle.js (app1主模塊)
module3.chunk.js (包含 module3.js 異步加載模塊)
modules~app1.chunk.js (包含app1獨有的模塊: 這裏暫時沒有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
複製代碼
app2.js相關:
app2.bundle.js (app2主模塊)
modules~app2.chunk.js (包含app2獨有的模塊: 這裏是module3.js)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
複製代碼
chunks
爲 all
時webpack對全部模塊進行分離,若是一個模塊既被異步引用,也被同部引用,那麼只會生成一個共享包,因此輸出結果爲:
app1.bundle.js
app2.bundle.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
複製代碼
app1.js相關:
app1.bundle.js ( app1 主模塊)
modules~app1.chunk.js (包含 app1 獨有的模塊: 這裏暫時沒有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js 模塊,雖然名字沒有 app1 ,可是能夠經過測試知道,app1 是依賴此模塊的,好比把此模塊刪除,而後在 index.html 中引入上面三個文件,查看控制檯就能知道 app1 依賴此模塊)
複製代碼
app2.js相關:
app2.bundle.js ( app2 主模塊)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js )
複製代碼
不知你注意到沒有,以上打包結果中,app1 的主模塊(app1.bundle.js)和app2的主模塊(app2.bundle.js)的文件名包含的是 bundle,而其餘模塊包含的是 chunk。
bundle 代表該代碼塊包含有 webpack 運行時 的代碼。而 chunk 則沒有。 那你可能會問,這樣 app1.bundle.js 和 app2.bundle.js 就包含了一樣的 webpack 運行時代碼,能夠把這份 webpack 運行時的代碼單獨分離出來做爲一個單獨的塊嗎? 答案是能夠的。
在 webpack.config.js 配置文件中添加如下屬性便可:
runtimeChunk: "single"
複製代碼
這樣在以上 chunks 爲 all 的示例中,輸出的結果爲:
app1.chunk.js
app2.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
runtime.bundle.js ( webpack 運行時模塊)
複製代碼
demo 代碼地址: github.com/SimpleCodeC…
倉庫代碼地址(及目錄): github.com/SimpleCodeC…
參考文檔: