1. SplitChunksPlugin的概念
起初乾巧,chunks(代碼塊)和導(dǎo)入他們中的模塊通過webpack內(nèi)部的父子關(guān)系圖連接.在webpack3中预愤,通過CommonsChunkPlugin來避免他們之間的依賴重復(fù)植康。而在webpack4中CommonsChunkPlugin被移除,取而代之的是 optimization.splitChunks 和 optimization.runtimeChunk 配置項,下面展示它們將如何工作存崖。
在默認(rèn)情況下睡毒,SplitChunksPlugin 僅僅影響按需加載的代碼塊,因為更改初始塊會影響HTML文件應(yīng)包含的腳本標(biāo)記以運行項目供搀。
webpack將根據(jù)以下條件自動拆分代碼塊:
- 會被共享的代碼塊或者 node_mudules 文件夾中的代碼塊
- 體積大于30KB的代碼塊(在gz壓縮前)
- 按需加載代碼塊時的并行請求數(shù)量不超過5個
- 加載初始頁面時的并行請求數(shù)量不超過3個
舉例1:
// index.js
// 動態(tài)加載 a.js
import('./a')
// a.js
import 'vue'
// ...
打包之后的結(jié)果會創(chuàng)建一個包含 vue 的獨立代碼塊,當(dāng)包含 a.js 的原始代碼塊被調(diào)用時趁曼,這個獨立代碼塊會并行請求進(jìn)來棕洋。
原因:
- vue 來自 node_modules 文件夾
- vue 體積超過30KB
- 導(dǎo)入調(diào)用時的并行請求數(shù)為2
- 不影響頁面初始加載
我們這樣做的原因是因為,vue代碼并不像你的業(yè)務(wù)代碼那樣經(jīng)常變動摄悯,把它單獨提取出來就可以和你的業(yè)務(wù)代碼分開緩存愧捕,極大的提高效率。
舉例2:
// entry.js
import("./a");
import("./b");
// a.js
import "./helpers"; // helpers is 40kb in size
// ...
// b.js
import "./helpers";
import "./more-helpers"; // more-helpers is also 40kb in size
// ...
結(jié)果:將創(chuàng)建一個單獨的塊,其中包含./helpers
它的所有依賴項管跺。在導(dǎo)入調(diào)用時禾进,此塊與原始塊并行加載。
原因:
- 條件1:
helpers
是共享塊 - 條件2:
helpers
大于30kb - 條件3:導(dǎo)入調(diào)用的并行請求數(shù)為2
- 條件4:不影響初始頁面加載時的請求
2. SplitChunksPlugin的默認(rèn)配置
以下是SplitChunksPlugin的默認(rèn)配置:
splitChunks: {
chunks: "async",
minSize: 30000, // 模塊的最小體積
minChunks: 1, // 模塊的最小被引用次數(shù)
maxAsyncRequests: 5, // 按需加載的最大并行請求數(shù)
maxInitialRequests: 3, // 一個入口最大并行請求數(shù)
automaticNameDelimiter: '~', // 文件名的連接符
name: true,
cacheGroups: { // 緩存組
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
緩存組:
緩存組因該是SplitChunksPlugin中最有趣的功能了艇拍。在默認(rèn)設(shè)置中卸夕,會將 node_mudules 文件夾中的模塊打包進(jìn)一個叫 vendors的bundle中婆瓜,所有引用超過兩次的模塊分配到 default bundle 中。更可以通過 priority 來設(shè)置優(yōu)先級碍讨。
chunks:
chunks屬性用來選擇分割哪些代碼塊蒙秒,可選值有:'all'(所有代碼塊),'async'(按需加載的代碼塊)覆获,'initial'(初始化代碼塊)瓢省。
3. 在項目中添加SplitChunksPlugin
為了方便演示,我們先安裝兩個類庫: lodash 和 axios摹量,
npm i lodash axios -S
修改 main.js馒胆,引入 lodash 和axios 并調(diào)用相應(yīng)方法:
import Modal from './components/modal/modal'
import './assets/style/common.less'
import _ from 'lodash'
import axios from 'axios'
const App = function () {
let div = document.createElement('div')
div.setAttribute('id', 'app')
document.body.appendChild(div)
let dom = document.getElementById('app')
let modal = new Modal()
dom.innerHTML = modal.template({
title: '標(biāo)題',
content: '內(nèi)容',
footer: '底部'
})
}
const app = new App()
console.log(_.camelCase('Foo Bar'))
axios.get('aaa')
使用SplitChunksPlugin不需要安裝任何依賴祝迂,只需在 webpack.config.js 中的 config對象添加 optimization 屬性:
optimization: {
splitChunks: {
chunks: 'initial',
automaticNameDelimiter: '.',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: 1
}
}
},
runtimeChunk: {
name: entrypoint => `manifest.${entrypoint.name}`
}
}
配置 runtimeChunk 會給每個入口添加一個只包含runtime的額外的代碼塊型雳,name 的值也可以是字符串,不過這樣就會給每個入口添加相同的 runtime纠俭,配置為函數(shù)時冤荆,返回當(dāng)前的entry對象,即可分入口設(shè)置不同的runtime匙赞。
我們再安裝一個 webpack-bundle-analyzer,這個插件會清晰的展示出打包后的各個bundle所依賴的模塊:
npm i webpack-bundle-analyzer -D
引入:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
使用,在plugins數(shù)組中添加即可:
new BundleAnalyzerPlugin()
打包之后:
?
?
各個模塊依賴清晰可見,打開 dist/index.html可見我們的代碼順利運行:
?
以上就是SplitChunksPlugin的基本用法匹中,更多高級的配置大家可以繼續(xù)鉆研(比如多入口應(yīng)用)。