webpack4以前,你們一直都是用CommonsChunkPlugin來作代碼切割。那用他具體有什麼坑呢?node
我用起來感受最詭異的點就是每次切割以後,新生成的chunk會和被提取的chunk生成一種父子關係(生成的公共chunk爲entry chunk,以前有寫過一篇文章介紹),即被提取的chunk會依賴於生成的chunk。下一次再作提取的時候,除非手動指定,只會掃描全部的entry chunk.react
感受CommonsChunkPlugin的表現也不是那麼穩定,以前寫了一個把node_modules裏面的module全打包到vendor chunk裏,明明minChunks屬性設置成了Infinity,線上仍是出了鍋,同事在node_modules裏面裝了一個包莫名其妙地被打到了業務代碼裏,害我出了一次事故。webpack
升級了webpack4以後,production模式下,SplitChunksPlugin插件是默認被啓用的,默認配置以下:web
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
複製代碼
這個配置是啥意思呢?老規矩,一個個參數的來看:正則表達式
async
, initial
, all
. 顧名思義,async針對異步加載的chunk作切割,initial針對初始chunk,all針對全部chunk。看到這裏八成是一臉懵逼,這特麼是在說啥?別急,具體來看幾個例子就清楚了:數組
const entry = {
index: "./src/index.jsx",
index2: './src/index2.jsx',
}
複製代碼
有index和index2兩個entry(都引用了react和react-dom):緩存
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
複製代碼
import React from 'react';
import ReactDOM from 'react-dom';
console.log(React, ReactDOM);
複製代碼
而後App.jsx長這樣:bash
import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader'
class App extends PureComponent {
render() {
return (
<div>App...</div>
)
}
}
export default hot(module)(App);
複製代碼
根據默認配置,是不會有任何切割的,由於咱們只對async代碼作切割。先把chunks改爲initial,build獲得以下結果:dom
如圖,全部node_modules裏面的引用都被打到了vendors~index~index2~.....裏面. 如今咱們再加一個group:異步
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
'react-vendor': {
test: (module, chunks) => /react/.test(module.context),
priority: 1,
},
複製代碼
build獲得以下結果:
由於react-vendor的優先級高,因此react相關module都被打到了react-vendor~index~index2-.....裏面。能夠看到index和index2 chunk裏都包含了fbjs 和lib包,這是由於這兩個包過小了,放到一塊兒生成的chunk size<咱們設置的30kb。咱們把minSize設置成3kb,再次build:
能夠看到fbjs和lib等小module被打到了vendors裏面(react相關的module之因此被打到react-vendor 而不是vendor就是由於react-vendor的優先級高於vendor。 若是把react-vendor的優先級改爲-11,則全部全部的module都會被打到vendor,不會生成react-vendor)。
接着咱們再來看一下minchunks,在index2裏咱們引用moment
import React from 'react';
import ReactDOM from 'react-dom';
import moment from 'moment';
console.log(React, ReactDOM, moment);
複製代碼
把vendor group的minchunks 設成2,覆蓋掉splitChunks裏面上面設置的1,build:
如圖,moment由於只被index2引用了一次,因此不會被提取出來.
除了這種簡單的提取,經過test咱們能夠拿到module的信息(目前我只用過他的路徑)和提取chunk的信息,而後本身進行組合來自定義生成新chunk。
vendors: {
test: (module, chunks) => {
let chunkName = '';
chunks.forEach(chunk => {
chunkName += chunk.name + ',';
})
console.log(module.context, chunkName, chunks.length);
return /node_modules/.test(module.context)
},
},
複製代碼
另外,若是須要作持久緩存的話,雖然runtime能夠經過設置runtimeChunk: true
來解決,可是moduleID,ChunkID的問題仍是須要HashedModuleIdsPlugin等插件來解決(webpack實現持久緩存)。
webpack 4: Code Splitting, chunk graph and the splitChunks optimization