CommonsChunkPlugin學(xué)習(xí)小結(jié)

Chunk

首先弄明白chunk是什么東西:webpack將多個(gè)模塊打包之后的代碼集合稱為chunk。

webpack里, chunk有三種類型:

  1. entry chunk: 含有webpack runtime代碼的模塊代碼集合。
  2. normal chunk:不含runtime代碼的模塊集合。
  3. initial chunk:文檔里講是一種特殊的normal chunk。 在加載的時(shí)候順序會(huì)在normal chunk前面(這個(gè)有興趣的同學(xué)可以深入了解一下)草姻。

另外有幾點(diǎn)需要注意的:

  1. entry chunk是必須要先于normal chunk加載的,因?yàn)槔锩姘膔untime代碼定義了一些列webpack要用到的函數(shù),不事先加載好目尖,后面的代碼webpack就沒法玩了。
  2. 每一個(gè)entry point都會(huì)對(duì)應(yīng)生成一個(gè)entry chunk扎运。
  3. 每一個(gè)用import()懶加載的模塊會(huì)對(duì)應(yīng)生成一個(gè)normal chunk瑟曲,這個(gè)chunk會(huì)依賴于調(diào)用import()的entry chunk,成為其child.

CommonsChunkPlugin

先貼一段官網(wǎng)自己的介紹:

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.

理解下來大概就是說:webpack打包的代碼都是以chunk的形式存儲(chǔ)的豪治。但是呢洞拨,不同chunk里可能存在相同的模塊,CommonsChunkplugin呢负拟,就是把這些不同chunk里重復(fù)的模塊提取出來放到一個(gè)公共chunk里烦衣。這個(gè)公共chunk只需要下載一次,就可以讓所有的chunk都使用了掩浙。而且這部分代碼可以放到緩存里琉挖,這樣以后就不用再下載了(另外有寫關(guān)于用webpack做緩存的文章,有興趣可以看看)涣脚。而且這么做每個(gè)chunk的代碼也少了示辈,所以每次加載的速度也更快。

那CommonsChunkplugin怎么用呢遣蚀?

常用參數(shù):

  1. 決定生成chunk的參數(shù): name, names, async
    name: string: 公共chunk的名字矾麻。如果傳入一個(gè)已經(jīng)存在的chunk名纱耻,那這個(gè)chunk就作為公共chunk存放提取出來的公共代碼.否則webpack會(huì)新建一個(gè)公共chunk。
    names: string[]: 和name一樣险耀,不過傳入的是一個(gè)數(shù)組弄喘。相當(dāng)于對(duì)數(shù)組中的每個(gè)元素做一次代碼切割。
    async: boolean|string: 把公共代碼提取到一個(gè)懶加載的chunk甩牺,在被使用到時(shí)才進(jìn)行下載蘑志,當(dāng)傳入值為string的時(shí)候,該值會(huì)被用來當(dāng)做懶加載chunk的名字贬派。目前來看一般都是配合children使用(entry chunk在app初始化的時(shí)候就會(huì)被加載急但,增加async標(biāo)簽沒什么意義)。

  2. 決定被提取的chunk: chunks, children, deepChildren
    chunks: string[]: webpack會(huì)從傳入的chunk里面提取公共代碼搞乏,如果不傳則從所有的entry chunk中提取波桩。
    children: boolean : 當(dāng)不設(shè)置children(deepChildren)的時(shí)候,webpack會(huì)從entry chunk中根據(jù)條件提取公共代碼请敦。 當(dāng)設(shè)置children為true時(shí)镐躲,webpack會(huì)從entry chunk的直接子chunk中提取代碼.
    deepChildren: boolean: 和children一樣,不過選取公共chunk的所有下屬節(jié)點(diǎn)侍筛。

  3. 決定提取條件: minChunks
    minChunks: number|infinity|function(module,count)->boolean: 如果傳入數(shù)字或infinity(默認(rèn)值為3)萤皂,就是告訴webpack,只有當(dāng)模塊重復(fù)的次數(shù)大于等于該數(shù)字時(shí)匣椰,這個(gè)模塊才會(huì)被提取出來裆熙。當(dāng)傳入為函數(shù)時(shí),所有符合條件的chunk中的模塊都會(huì)被傳入該函數(shù)做計(jì)算窝爪,返回true的模塊會(huì)被提取到目標(biāo)chunk。

總結(jié)一下:

  • webpack里面就entry chunk, normal chunk兩種齐媒,在沒有手動(dòng)設(shè)置chunks的情況下蒲每,如果要提取normal chunk里的公共代碼,那就把children(deepChildren)設(shè)為true喻括。否則提取的就是entry chunk邀杏。如果對(duì)webpack這兩種分類不滿意,那就用chunks手動(dòng)指定要選取的chunk唬血。
  • 如果你希望對(duì)打包出來的公共chunk做一個(gè)懶加載望蜡,把a(bǔ)sync設(shè)成true。
  • 通過minChunks來決定要把哪些模塊提取到公共chunk

再看幾個(gè)樣例:

case 1
兩個(gè)entry App 和 page1 都使用了 react拷恨, react-dom 和 classnames脖律, 我們要把重復(fù)出現(xiàn)2次以上的module都提取到一個(gè)公共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,
        }),

!出現(xiàn)2次的react,react-dom腕侄,classnames都被打包到vendor里](http://upload-images.jianshu.io/upload_images/10204068-1809ef63506b15b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

case 2
繼續(xù)case1的例子小泉,我們可以看到axios這個(gè)包依然和app的業(yè)務(wù)代碼混在一起芦疏。再提取一下把他單獨(dú)拉出來:

new webpack.optimize.CommonsChunkPlugin({
            name: 'axios',
            chunks: ['app'],
            minChunks: function(module) {
                return /axios/.test(module.context);
            }
        }),
axios被單獨(dú)提取到axios.js

當(dāng)然這里是為了寫chunks的使用樣例,實(shí)際操作中大可不必這樣提取兩次微姊。直接在第一次提取的時(shí)候把node_modules里面的庫都打到vendor里就好了(minChunks: 1也行)

case 3
子chunk存在的情況酸茴,這里我選擇把子chunk提取到一個(gè)新的懶加載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';
打包結(jié)果
new webpack.optimize.CommonsChunkPlugin({
            name: 'app',
            async: 'vendor',
            children: true,
            minChunks: 2,
        }),

如圖薪捍,相當(dāng)于告訴webpack,掃描app(entry chunk)直接子chunk(Home, Topics, About)里的模塊配喳,把出現(xiàn)次數(shù)不少于2次的提取出來放到一個(gè)叫vendor的懶加載模塊中去酪穿。


打包結(jié)果

case 4
其實(shí)除了提取公共模塊之外,用CommonsChunkPlugin做前端工程的代碼切割也非常好用界逛。
為了更好的利用緩存昆稿,假設(shè)我們有如下需求:

  1. webpack runtime(entry chunk): 上面提到了,runtime的代碼必須先于其他代碼執(zhí)行息拜。并且由于runtime代碼隨著module和chunk ID的變化會(huì)經(jīng)常變動(dòng)溉潭,所以建議單獨(dú)打包出來

  2. lib(normal chunk): lib里放一些如react, react-dom, react-router等基本不會(huì)改變的基礎(chǔ)庫。

  3. vendor(normal chunk): vendor里放一些如 axios少欺,moment等偶爾變化的工具庫

  4. 業(yè)務(wù)代碼(normal chunk): 隨時(shí)都在變喳瓣,單獨(dú)放一個(gè)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此時(shí)變?yōu)閚ormal chunk。

第三次打包: 從所有entry chunk(vendor)中提取出路徑含有react的模塊底循,放入chunk lib.

第四次打包: 新建一個(gè)manifest chunk,不放入任何模塊(minChunks:infinity)仿滔。由于manifest是此時(shí)唯一的entry chunk惠毁,則runtime代碼放入manifest。

打包結(jié)果

如圖崎页,業(yè)務(wù)代碼和lib代碼鞠绰,vendor工具代碼等都完全分離。

參考文獻(xiàn)

CommonsChunkPlugin

Code Splitting

Vendor and code splitting in webpack 2

webpack: Unraveling CommonsChunkPlugin

webpack bits: Getting the most out of the CommonsChunkPlugin()

Added deepChildren support from ArcEglos' pull request

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末飒焦,一起剝皮案震驚了整個(gè)濱河市蜈膨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牺荠,老刑警劉巖翁巍,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異休雌,居然都是意外死亡灶壶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門杈曲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來例朱,“玉大人孝情,你說我怎么就攤上這事∪鬣停” “怎么了箫荡?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長渔隶。 經(jīng)常有香客問我羔挡,道長,這世上最難降的妖魔是什么间唉? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任绞灼,我火速辦了婚禮,結(jié)果婚禮上呈野,老公的妹妹穿的比我還像新娘低矮。我一直安慰自己,他們只是感情好被冒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布军掂。 她就那樣靜靜地躺著,像睡著了一般昨悼。 火紅的嫁衣襯著肌膚如雪蝗锥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天率触,我揣著相機(jī)與錄音终议,去河邊找鬼。 笑死葱蝗,一個(gè)胖子當(dāng)著我的面吹牛穴张,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播两曼,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皂甘,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了合愈?” 一聲冷哼從身側(cè)響起叮贩,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤击狮,失蹤者是張志新(化名)和其女友劉穎佛析,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彪蓬,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寸莫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了档冬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膘茎。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桃纯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出披坏,到底是詐尸還是另有隱情态坦,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布棒拂,位于F島的核電站伞梯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏帚屉。R本人自食惡果不足惜谜诫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望攻旦。 院中可真熱鬧喻旷,春花似錦、人聲如沸牢屋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伟阔。三九已至辣之,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皱炉,已是汗流浹背怀估。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留合搅,地道東北人多搀。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像灾部,于是被迫代替她去往敵國和親康铭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • GitChat技術(shù)雜談 前言 本文較長赌髓,為了節(jié)省你的閱讀時(shí)間从藤,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,697評(píng)論 7 110
  • 本文來自尚妝前端團(tuán)隊(duì)南洋發(fā)表于尚妝github博客锁蠕,歡迎訂閱夷野。 分割webpack配置文件的多種方法 (一) 將你...
    尚妝產(chǎn)品技術(shù)刊讀閱讀 4,795評(píng)論 1 15
  • 前端將大型項(xiàng)目分成一個(gè)個(gè)單獨(dú)的模塊,一般封裝好的每個(gè)模塊都會(huì)實(shí)現(xiàn)一個(gè)目的明確的完成的功能荣倾。如何處理這些模塊以及模塊...
    pixels閱讀 3,425評(píng)論 1 14
  • 目錄第1章 webpack簡介 11.1 webpack是什么悯搔? 11.2 官網(wǎng)地址 21.3 為什么使用 web...
    lemonzoey閱讀 1,736評(píng)論 0 1
  • webpack 介紹 webpack 是什么 為什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert閱讀 6,464評(píng)論 2 71