webpack dllplugin的使用姿勢(shì)

之前在上家公司计盒,主要負(fù)責(zé)系統(tǒng)后臺(tái)的業(yè)務(wù)蛤奥,由于業(yè)務(wù)代碼較冗余亏拉,一直在嘗試使用webpack dllplugin赶舆,由于業(yè)務(wù)線的耽誤,一直沒有時(shí)間優(yōu)化生巡,今天有時(shí)間,重新梳理了一下,整理一下描滔,分享給大家,webpack dllplugin的正確姿勢(shì)

part I:webpack dllplugin的配置

  1. 配置一份webpack配置文件踪古,用于生成動(dòng)態(tài)鏈接庫含长。例如,我們命名為webpack.dll.config.js.
const rootPath = path.resolve(__dirname, '../');
const isPro = process.env.NODE_ENV === 'production';

module.exports = {
    entry:  {
        vendor: ['react', 'react-dom']
    },
    output: {
        path: path.join(rootPath, 'dist/site'),
        filename: 'dll_[name].js',
        library: "[name]_[hash]"
    },
    plugins: [
        new webpack.DllPlugin({
            path: path.join(rootPath, "dist/site", "[name]-manifest.json"),
            name: "[name]_[hash]"
        })
    ]
}

這里output里的filename就是生成的文件名稱伏穆,這里也就是dll_vendor.js.而library是動(dòng)態(tài)庫輸出的模塊全局變量名稱拘泞。注意,這個(gè)library一定要與webpack.DllPlugin配置中的name完全一樣枕扫。為什么呢陪腌?
看一下,生成的manifest文件以及dll_vendor文件就明白了烟瞧。

dll_vendor.js文件如下:(這里為了清晰诗鸭,沒有壓縮)

var vendor_868ab5aa63db7c7c0a32 =
/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

注意library的作用,見官網(wǎng)参滴。配置了library强岸,就會(huì)默認(rèn)生成上述格式的文件。
vendor-manifest.json文件如下:

{"name":"vendor_868ab5aa63db7c7c0a32","content":{"./node_modules/process/browser.js":{"id":0,"meta":{}},

也就是說砾赔,這里是一種對(duì)應(yīng)的關(guān)系蝌箍,只用vendor-manifest文件中的name與真正的變量一致,才能被找到过蹂。

  1. 使用動(dòng)態(tài)鏈接庫十绑,黃金搭檔DllReferencePlugin。
new DllReferencePlugin({
  // 描述 react 動(dòng)態(tài)鏈接庫的文件內(nèi)容
  manifest: require('../dist/site/vendor-manifest.json'),
})
  1. 引用文件酷勺。
    這一步本橙,經(jīng)常會(huì)被忘記。一定要在HtmlWebpackPlugin的template 模版html文件中脆诉,手動(dòng)引入dll_vendor.js文件甚亭。
<body>
    <div id="app"></div>
    <script src="./dll_vendor.js"></script>
</body>

經(jīng)過上述三個(gè)步驟后,就大功告成了击胜。無論是正式環(huán)境build亏狰,還是webpack-dev-server都能引用dll文件。

part II:簡(jiǎn)單分析源碼

這里是really 簡(jiǎn)單分析偶摔,不深入探討暇唾,后續(xù)會(huì)陸續(xù)輸出webpack的系列文章,再具體討論每個(gè)plugin的實(shí)現(xiàn)細(xì)節(jié)。

很明顯策州,只涉及了webpackDllPlugin以及webpackReferencePlugin瘸味,那么這一part的研究對(duì)象就是這兩位了。

  1. webpackDllPlugin够挂。
    首先旁仿,我們已經(jīng)知道,webpackDllPlugin的作用就是做了兩件小事:根據(jù)entry孽糖,生成一份vendor文件枯冈;生成一份manifest.json文件。
/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
    */
"use strict";

const DllEntryPlugin = require("./DllEntryPlugin");
const LibManifestPlugin = require("./LibManifestPlugin");
const FlagInitialModulesAsUsedPlugin = require("./FlagInitialModulesAsUsedPlugin");

class DllPlugin {
    constructor(options) {
        this.options = options;
    }

    apply(compiler) {
        compiler.plugin("entry-option", (context, entry) => {
            function itemToPlugin(item, name) {
                if(Array.isArray(item))
                    return new DllEntryPlugin(context, item, name);
                else
                    throw new Error("DllPlugin: supply an Array as entry");
            }
            if(typeof entry === "object" && !Array.isArray(entry)) {
                Object.keys(entry).forEach(name => {
                    compiler.apply(itemToPlugin(entry[name], name));
                });
            } else {
                compiler.apply(itemToPlugin(entry, "main"));
            }
            return true;
        });

        compiler.apply(new LibManifestPlugin(this.options));
        compiler.apply(new FlagInitialModulesAsUsedPlugin());
    }
}

module.exports = DllPlugin;

其中LibManifestPlugin用于生成對(duì)應(yīng)的manifest.json文件办悟。

  1. webpackReferencePlugin尘奏。

源碼片段如下,我添加了核心的兩處注釋:

compiler.plugin("before-compile", (params, callback) => {
    const manifest = this.options.manifest;
    if(typeof manifest === "string") {
        // 將manifest加入到依賴dependency中
        params.compilationDependencies.push(manifest);
        // 讀取manifest.json的內(nèi)容
        compiler.inputFileSystem.readFile(manifest, function(err, result) {
            if(err) return callback(err);
            params["dll reference " + manifest] = JSON.parse(result.toString("utf-8"));
            return callback();
        });
    } else {
        return callback();
    }
});

compiler.plugin("compile", (params) => {
    let manifest = this.options.manifest;
    if(typeof manifest === "string") {
        manifest = params["dll reference " + manifest];
    }
    const name = this.options.name || manifest.name;
    const sourceType = this.options.sourceType || (manifest && manifest.type) || "var";
    const externals = {};
    const source = "dll-reference " + name;
    externals[source] = name;
    //將manifest的文件依賴,以external形式打包(external是作為外部依賴誉尖,不進(jìn)行pack的)
    params.normalModuleFactory.apply(new ExternalModuleFactoryPlugin(sourceType, externals));
    params.normalModuleFactory.apply(new DelegatedModuleFactoryPlugin({
        source: source,
        type: this.options.type,
        scope: this.options.scope,
        context: this.options.context || compiler.options.context,
        content: this.options.content || manifest.content,
        extensions: this.options.extensions
    }));
});

part III:總結(jié)
webpack DllPlugin優(yōu)化罪既,使用于將項(xiàng)目依賴的基礎(chǔ)模塊(第三方模塊)抽離出來,然后打包到一個(gè)個(gè)單獨(dú)的動(dòng)態(tài)鏈接庫中铡恕。當(dāng)下一次打包時(shí)琢感,通過webpackReferencePlugin,如果打包過程中發(fā)現(xiàn)需要導(dǎo)入的模塊存在于某個(gè)動(dòng)態(tài)鏈接庫中探熔,就不能再次被打包驹针,而是去動(dòng)態(tài)鏈接庫中g(shù)et到。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诀艰,一起剝皮案震驚了整個(gè)濱河市柬甥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌其垄,老刑警劉巖苛蒲,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绿满,居然都是意外死亡臂外,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門喇颁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漏健,“玉大人,你說我怎么就攤上這事橘霎∧杞” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵姐叁,是天一觀的道長(zhǎng)瓦盛。 經(jīng)常有香客問我洗显,道長(zhǎng),這世上最難降的妖魔是什么谭溉? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任墙懂,我火速辦了婚禮,結(jié)果婚禮上扮念,老公的妹妹穿的比我還像新娘。我一直安慰自己碧库,他們只是感情好柜与,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嵌灰,像睡著了一般弄匕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沽瞭,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天迁匠,我揣著相機(jī)與錄音,去河邊找鬼驹溃。 笑死城丧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豌鹤。 我是一名探鬼主播亡哄,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼布疙!你這毒婦竟也來了蚊惯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤灵临,失蹤者是張志新(化名)和其女友劉穎截型,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儒溉,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宦焦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了睁搭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赶诊。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖园骆,靈堂內(nèi)的尸體忽然破棺而出舔痪,到底是詐尸還是另有隱情,我是刑警寧澤锌唾,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布锄码,位于F島的核電站夺英,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏滋捶。R本人自食惡果不足惜痛悯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望重窟。 院中可真熱鬧载萌,春花似錦、人聲如沸巡扇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厅翔。三九已至乖坠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刀闷,已是汗流浹背熊泵。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甸昏,地道東北人顽分。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筒扒,于是被迫代替她去往敵國和親怯邪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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