webpack多頁應(yīng)用架構(gòu)系列(十一):預(yù)打包Dll暇咆,實(shí)現(xiàn)webpack音速編譯

本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意婆翔,請勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000007104372
如果您對本系列文章感興趣掏婶,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang

前言

書承上文《webpack多頁應(yīng)用架構(gòu)系列(十):如何打造一個(gè)自定義的bootstrap》啃奴。

上文說到我們利用webpack來打包一個(gè)可配置的bootstrap,但文末留下一個(gè)問題:由于bootstrap十分龐大雄妥,因此每次編譯都要耗費(fèi)大部分的時(shí)間在打包bootstrap這一塊最蕾,而換來的僅僅是配置的便利,十分不劃算老厌。

我也并非是故意賣關(guān)子瘟则,這的確是我自己開發(fā)中碰到的問題,而在撰寫完該文后枝秤,我立即著手探索解決之道醋拧。終于,發(fā)現(xiàn)了webpack這一大殺器:DllPlugin&DllReferencePlugin淀弹,打包時(shí)間過長的問題得到完美解決丹壕。

解決方案的機(jī)制和原理

DllPlugin&DllReferencePlugin這一方案,實(shí)際上也是屬于代碼分割的范疇薇溃,但與CommonsChunkPlugin不一樣的是菌赖,它不僅僅是把公用代碼提取出來放到一個(gè)獨(dú)立的文件供不同的頁面來使用,它更重要的一點(diǎn)是:把公用代碼和它的使用者(業(yè)務(wù)代碼)從編譯這一步就分離出來沐序,換句話說琉用,我們可以分別來編譯公用代碼和業(yè)務(wù)代碼了忿峻。這有什么好處呢?很簡單辕羽,業(yè)務(wù)代碼常改逛尚,而公用代碼不常改,那么刁愿,我們在日常修改業(yè)務(wù)代碼的過程中绰寞,就可以省出編譯公用代碼那一部分所耗費(fèi)的時(shí)間了(是不是馬上就聯(lián)想到坑爹的bootstrap了呢)。

整個(gè)過程大概是這樣的:

  1. 利用DllPlugin把公用代碼打包成一個(gè)“Dll文件”(其實(shí)本質(zhì)上還是js铣口,只是套用概念而已)滤钱;除了Dll文件外,DllPlugin還會生成一個(gè)manifest.json文件作為公用代碼的索引供DllReferencePlugin使用脑题。
  2. 在業(yè)務(wù)代碼的webpack配置文件中配置好DllReferencePlugin并進(jìn)行編譯件缸,達(dá)到利用DllReferencePlugin讓業(yè)務(wù)代碼和Dll文件實(shí)現(xiàn)關(guān)聯(lián)的目的。
  3. 在各個(gè)頁面<head>中叔遂,先加載Dll文件他炊,再加載業(yè)務(wù)代碼文件。

適用范圍

Dll文件里只適合放置不常改動的代碼已艰,比如說第三方庫(誰也不會有事無事就升級一下第三方庫吧)痊末,尤其是本身就龐大或者依賴眾多的庫。如果你自己整理了一套成熟的框架哩掺,開發(fā)項(xiàng)目時(shí)只需要在上面添磚加瓦的凿叠,那么也可以把這套框架也打包進(jìn)Dll文件里,甚至可以做到多個(gè)項(xiàng)目共用這一份Dll文件嚼吞。

如何配置哪些代碼需要打包進(jìn)Dll文件盒件?

我們需要專門為Dll文件建一份webpack配置文件,不能與業(yè)務(wù)代碼共用同一份配置:

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const dirVars = require('./webpack-config/base/dir-vars.config.js'); // 與業(yè)務(wù)代碼共用同一份路徑的配置表

module.exports = {
  output: {
    path: dirVars.dllDir,
    filename: '[name].js',
    library: '[name]', // 當(dāng)前Dll的所有內(nèi)容都會存放在這個(gè)參數(shù)指定變量名的一個(gè)全局變量下舱禽,注意與DllPlugin的name參數(shù)保持一致
  },
  entry: {
    /*
      指定需要打包的js模塊
      或是css/less/圖片/字體文件等資源炒刁,但注意要在module參數(shù)配置好相應(yīng)的loader
    */
    dll: [
      'jquery', '!!bootstrap-webpack!bootstrapConfig',
      'metisMenu/metisMenu.min', 'metisMenu/metisMenu.min.css',
    ],
  },
  plugins: [
    new webpack.DllPlugin({
      path: 'manifest.json', // 本Dll文件中各模塊的索引,供DllReferencePlugin讀取使用
      name: '[name]',  // 當(dāng)前Dll的所有內(nèi)容都會存放在這個(gè)參數(shù)指定變量名的一個(gè)全局變量下呢蔫,注意與參數(shù)output.library保持一致
      context: dirVars.staticRootDir, // 指定一個(gè)路徑作為上下文環(huán)境切心,需要與DllReferencePlugin的context參數(shù)保持一致飒筑,建議統(tǒng)一設(shè)置為項(xiàng)目根目錄
    }),
    /* 跟業(yè)務(wù)代碼一樣片吊,該兼容的還是得兼容 */
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      'window.$': 'jquery',
    }),
    new ExtractTextPlugin('[name].css'), // 打包c(diǎn)ss/less的時(shí)候會用到ExtractTextPlugin
  ],
  module: require('./webpack-config/module.config.js'), // 沿用業(yè)務(wù)代碼的module配置
  resolve: require('./webpack-config/resolve.config.js'), // 沿用業(yè)務(wù)代碼的resolve配置
};

如何編譯Dll文件?

編譯Dll文件的代碼實(shí)際上跟編譯業(yè)務(wù)代碼是一樣的协屡,記得利用--config指定上述專供Dll使用的webpack配置文件就好了:

$ webpack --progress --colors --config ./webpack-dll.config.js

另外俏脊,建議可以把該語句寫到npm scripts里,好記一點(diǎn)哈肤晓。

如何讓業(yè)務(wù)代碼關(guān)聯(lián)Dll文件爷贫?

我們需要在供編譯業(yè)務(wù)代碼的webpack配置文件里設(shè)好DllReferencePlugin的配置項(xiàng):

new webpack.DllReferencePlugin({
  context: dirVars.staticRootDir, // 指定一個(gè)路徑作為上下文環(huán)境认然,需要與DllPlugin的context參數(shù)保持一致,建議統(tǒng)一設(shè)置為項(xiàng)目根目錄
  manifest: require('../../manifest.json'), // 指定manifest.json
  name: 'dll',  // 當(dāng)前Dll的所有內(nèi)容都會存放在這個(gè)參數(shù)指定變量名的一個(gè)全局變量下漫萄,注意與DllPlugin的name參數(shù)保持一致
});

配置好DllReferencePlugin了以后卷员,正常編譯業(yè)務(wù)代碼即可。不過要注意腾务,必須要先編譯Dll并生成manifest.json后再編譯業(yè)務(wù)代碼毕骡;而以后每次修改Dll并重新編譯后,也要重新編譯一下業(yè)務(wù)代碼岩瘦。

如何在業(yè)務(wù)代碼里使用Dll文件打包的module/資源未巫?

不需要刻意做些什么,該怎么require就怎么require启昧,webpack都會幫你處理好的了叙凡。

如何整合Dll?

在每個(gè)頁面里密末,都要按這個(gè)順序來加載js文件:Dll文件 => CommonsChunkPlugin生成的公用chunk文件(如果沒用CommonsChunkPlugin那就忽略啦) => 頁面本身的入口文件握爷。

有兩個(gè)注意事項(xiàng):

  • 如果你是像我一樣利用HtmlWebpackPlugin來生成HTML并自動加載chunk的話,請務(wù)必在<head>里手寫<script>來加載Dll文件严里。
  • 為了完全分離源文件和編譯后生成的文件饼拍,也為了方便在編譯前可以清空build目錄,不應(yīng)直接把Dll文件編譯生成到build目錄里田炭,我建議可以先生成到源文件src目錄里师抄,再用file-loader給原封不動搬運(yùn)過去。

光說不練假把式教硫,來個(gè)跑分啊大兄弟叨吮!

下面以我的腳手架項(xiàng)目Array-Huang/webpack-seed為例,測試一下(使用開發(fā)環(huán)境的webpack配置文件webpack.dev.config.js)使用這套Dll方案前后的webpack編譯時(shí)間:

  • 使用Dll方案前的編譯時(shí)間為:10秒17
  • 使用Dll方案后的編譯時(shí)間為:4秒29

由于該項(xiàng)目只是一個(gè)腳手架瞬矩,涉及到的第三方庫并不多茶鉴,我只把jQuery、bootstrap景用、metisMenu給打包進(jìn)Dll文件里了涵叮,盡管如此,還是差了將近6秒了伞插,相信在實(shí)際項(xiàng)目中割粮,這套DllPlugin&DllReferencePlugin的方案能為你省下更多的時(shí)間來找女朋友(大誤)。

示例代碼

諸位看本系列文章媚污,搭配我在Github上的腳手架項(xiàng)目食用更佳哦(笑):Array-Huang/webpack-seedhttps://github.com/Array-Huang/webpack-seed)舀瓢。

附系列文章目錄(同步更新)

本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意绞吁,請勿轉(zhuǎn)載幢痘。
原文地址:https://segmentfault.com/a/1190000007104372
如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末家破,一起剝皮案震驚了整個(gè)濱河市颜说,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汰聋,老刑警劉巖门粪,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異烹困,居然都是意外死亡玄妈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門髓梅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拟蜻,“玉大人,你說我怎么就攤上這事枯饿≡凸” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵奢方,是天一觀的道長搔扁。 經(jīng)常有香客問我,道長蟋字,這世上最難降的妖魔是什么稿蹲? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮愉老,結(jié)果婚禮上场绿,老公的妹妹穿的比我還像新娘剖效。我一直安慰自己嫉入,他們只是感情好焰盗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咒林,像睡著了一般熬拒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垫竞,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天澎粟,我揣著相機(jī)與錄音,去河邊找鬼欢瞪。 笑死活烙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遣鼓。 我是一名探鬼主播啸盏,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骑祟!你這毒婦竟也來了回懦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤次企,失蹤者是張志新(化名)和其女友劉穎怯晕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缸棵,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舟茶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堵第。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稚晚。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖型诚,靈堂內(nèi)的尸體忽然破棺而出客燕,到底是詐尸還是另有隱情,我是刑警寧澤狰贯,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布也搓,位于F島的核電站,受9級特大地震影響涵紊,放射性物質(zhì)發(fā)生泄漏傍妒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一摸柄、第九天 我趴在偏房一處隱蔽的房頂上張望颤练。 院中可真熱鬧,春花似錦驱负、人聲如沸嗦玖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宇挫。三九已至苛吱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間器瘪,已是汗流浹背翠储。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留橡疼,地道東北人援所。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像欣除,于是被迫代替她去往敵國和親任斋。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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