首先,重要的事情放在開頭:前端
Webpack4 下個月就出了,CommonsChunkplugin被幹掉了!node
若是你還有興趣,那就一塊兒來看看吧。react
首先弄明白chunk是什麼東西:webpack將多個模塊打包以後的代碼集合稱爲chunk。webpack
webpack裏, chunk有三種類型:ios
另外有幾點須要注意的:git
先貼一段官網本身的介紹:github
The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.web
理解下來大概就是說:webpack打包的代碼都是以chunk的形式存儲的。可是呢,不一樣chunk裏可能存在相同的模塊,CommonsChunkplugin呢,就是把這些不一樣chunk裏重複的模塊提取出來放到一個公共chunk裏。這個公共chunk只須要下載一次,就可讓全部的chunk都使用了。並且這部分代碼能夠放到緩存裏,這樣之後就不用再下載了(另外有寫關於用webpack作緩存的文章,有興趣能夠看看)。並且這麼作每一個chunk的代碼也少了,因此每次加載的速度也更快。axios
經常使用參數:數組
1.決定生成chunk的參數: name, names, async
name: string: 公共chunk的名字。若是傳入一個已經存在的chunk名,那這個chunk就做爲公共chunk存放提取出來的公共代碼.不然webpack會新建一個公共chunk。
names: string[]: 和name同樣,不過傳入的是一個數組。至關於對數組中的每一個元素作一次代碼切割。
async: boolean|string: 把公共代碼提取到一個懶加載的chunk,在被使用到時才進行下載,當傳入值爲string的時候,該值會被用來當作懶加載chunk的名字。目前來看通常都是配合children使用(entry chunk在app初始化的時候就會被加載,增長async標籤沒什麼意義)。
2.決定被提取的chunk: chunks, children, deepChildren
chunks: string[]: webpack會從傳入的chunk裏面提取公共代碼,若是不傳則從全部的entry chunk中提取。 children: boolean : 當不設置children(deepChildren)的時候,webpack會從entry chunk中根據條件提取公共代碼。 當設置children爲true時,webpack會從entry chunk的直接子chunk中提取代碼. deepChildren: boolean: 和children同樣,不過選取公共chunk的全部下屬節點。
3.決定提取條件: minChunks
minChunks: number|infinity|function(module,count)->boolean: 若是傳入數字或infinity(默認值爲3),就是告訴webpack,只有當模塊重複的次數大於等於該數字時,這個模塊纔會被提取出來。當傳入爲函數時,全部符合條件的chunk中的模塊都會被傳入該函數作計算,返回true的模塊會被提取到目標chunk。
囉嗦了一大堆,總結一下:
再看幾個樣例:
case 1
兩個entry App 和 page1 都使用了 react, react-dom 和 classnames, 咱們要把重複出現2次以上的module都提取到一個公共chunk vendor裏: App:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as axios from 'axios';
import * as classnames from 'classnames';
複製代碼
Page1:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as classnames from 'classnames';
複製代碼
webpack配置:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2,
}),
複製代碼
case 2
繼續case1的例子,咱們能夠看到axios這個包依然和app的業務代碼混在一塊兒。再提取一下把他單獨拉出來:
new webpack.optimize.CommonsChunkPlugin({
name: 'axios',
chunks: ['app'],
minChunks: function(module) {
return /axios/.test(module.context);
}
}),
複製代碼
固然這裏是爲了寫chunks的使用樣例,實際操做中大可沒必要這樣提取兩次。直接在第一次提取的時候把node_modules裏面的庫都打到vendor裏就行了(minChunks: 1也行)
case 3
子chunk存在的狀況,這裏我選擇把子chunk提取到一個新的懶加載chunk裏: App異步引用Home,Topics,About:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as moment from 'axios';
import * as classnames from 'classnames';
const Home = () => import('./Home');
const Topics = () => import('./Topics');
const About = () => import('./About');
複製代碼
Home,Topic,About都引用mobx和moment
import * as React from 'react';
import * as moment from 'moment';
import * as mobx from 'mobx';
複製代碼
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor',
children: true,
minChunks: 2,
}),
複製代碼
如圖,至關於告訴webpack,掃描app(entry chunk)直接子chunk(Home, Topics, About)裏的模塊,把出現次數很多於2次的提取出來放到一個叫vendor的懶加載模塊中去。
case 4
其實除了提取公共模塊以外,用CommonsChunkPlugin作前端工程的代碼切割也很是好用。 爲了更好的利用緩存,假設咱們有以下需求:
webpack runtime(entry chunk): 上面提到了,runtime的代碼必須先於其餘代碼執行。而且因爲runtime代碼隨着module和chunk ID的變化會常常變更,因此建議單獨打包出來
lib(normal chunk): lib裏放一些如react, react-dom, react-router等基本不會改變的基礎庫。
vendor(normal chunk): vendor裏放一些如 axios,moment等偶爾變化的工具庫
業務代碼(normal chunk): 隨時都在變,單獨放一個chunk
直接上配置:
new webpack.optimize.CommonsChunkPlugin({
deepChildren: true,
async: 'async-vendor',
minChunks: function (module) {
return /node_modules/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return /node_modules/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "lib",
minChunks: function (module) {
return /react/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
複製代碼
第一次打包:從全部entry chunk(app, page1)的直接子chunk(Home,Topics,About)中提取出公共模塊(mobx, moment)放入懶加載chunk async-vendor中。
第二次打包: 從全部entry chunk(app, page1)中提取出node_modules裏的模塊放入chunk vendor中。app, page1此時變爲normal chunk。
第三次打包: 從全部entry chunk(vendor)中提取出路徑含有react的模塊,放入chunk lib.
第四次打包: 新建一個manifest chunk,不放入任何模塊(minChunks:infinity)。因爲manifest是此時惟一的entry chunk,則runtime代碼放入manifest。
如圖,業務代碼和lib代碼,vendor工具代碼等都徹底分離。
Vendor and code splitting in webpack 2
webpack: Unraveling CommonsChunkPlugin
webpack bits: Getting the most out of the CommonsChunkPlugin()