Webpack Code Splitting - Libraries

Code Splitting - Libraries

文檔地址
應(yīng)用程序一般會使用第三方的類庫,這些類庫一般不會經(jīng)常變動。
而我們的業(yè)務(wù)代碼需要隨著業(yè)務(wù)改變經(jīng)常更新。
webapp為了提升效率,會根據(jù)cache header中的參數(shù)對文件進行緩存,
文件緩存之后就不需要再從cdn上從新拉去資源了。
為了使用緩存特性,我們需要將vendor文件進行緩存,無論我們的業(yè)務(wù)代碼如何改變,
都不希望重新下載不變的vendor文件。
我們可以通過將代碼分離成vendor bundle和application bundle來使用該特性。

單入口配置

不拆分的配置方法,比如我們在應(yīng)用中使用(momentjs)[https://www.npmjs.com/package/moment],用來格式化時間的js類。

安裝moment,https://www.npmjs.com/package/moment.
在index.js中引入moment,并使用其打印當前時間。

//index.js
var moment = require('moment');
console.log(moment().format());

使用如下配置進行打包

var path = require('path');

module.exports = function(env) {
    return {
        entry: './index.js',
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        }
    }
}

在運行webpack進行打包之后,分析resulting bundle,會發(fā)現(xiàn)momentindex.js被打包到了同一個文件中(bundle.js)。

上面的方案,對于應(yīng)用來講,是不完美的,如果index.js代碼變了,那涉及到的bundle,都會進行重新編譯。瀏覽器會重新加載所有的bundle,雖然很多bundle沒有改變。

多入口配置(Multiple Entries)

momentvendor分離,實現(xiàn)更改index.js不影響vendor。

var path = require('path');

module.exports = function(env) {
    return {
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        }
    }
}

按照上面的配置,運行webpack后,將會生成兩個bundle。
查看這兩個bundle文件,將會看到兩個文件中都包含moment文件。
這是因為moment是主程序(index.js)的依賴.所以兩個entry point中都會出現(xiàn)moment.
這樣配置沒有實現(xiàn)我們的預(yù)期。為了解決這個問題,需要使用CommonsChunkPlugin

CommonsChunkPlugin

該plugin有些復(fù)雜,使用該plugin可以將不同bundle中的公共模塊抽出來放在公用的bundle中。
如果該公用的bundle不存在,會創(chuàng)建一個新的bundle。
使用下面的配置啟用CommonsChunkPlugin.

var webpack = require('webpack');
var path = require('path');

module.exports = function(env) {
    return {
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor' // Specify the common bundle's name.
            })
        ]
    }
}

經(jīng)過上面的配置,執(zhí)行webpack,查看打包的bundle,moment代碼只會存在于vendor bundle。
這樣對index.js的修改,就不會導(dǎo)致全部文件進行重新打包了。

Implicit Common Vendor Chunk

可以配置CommonsChunkPlugin僅僅對vendor lib起作用。

var webpack = require('webpack');
var path = require('path');

module.exports = function() {
    return {
        entry: {
            main: './index.js'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                minChunks: function (module) {
                   // this assumes your vendor imports exist in the node_modules directory
                   return module.context && module.context.indexOf('node_modules') !== -1;
                }
            })
        ]
    };
}

Manifest File

如果再次運行webpack命令,會看到vendor文件的hash值被改變了。雖然通過配置將vendormain bundle進行了拆分。
但是我們觀察到,當業(yè)務(wù)代碼改變后,vendor bundle也會進行改變。這樣我們就仍然無法使用瀏覽器的緩存功能。
產(chǎn)生這種情況是因為每次構(gòu)建,webpack都會生成一些webpack的運行時代碼(runtime code),
webpack需要依賴runtime code才能真正的向用戶提供訪問的內(nèi)容。
當僅有一個單獨bundle時,runtime code會包含與該bundle中。
但是當生成多個bundles時,runtime code會唄抽取到公用的module(此處位vendor文件)
由于是抽取到了vendor中,所以業(yè)務(wù)代碼改變,仍然會影響vendor。

為了避免這個問題,需要將runtime代碼拆分到一個單獨的manifest文件,
雖然這樣做會導(dǎo)致多生成一個bundle文件,但是這樣就能使用瀏覽器的緩存機制了。
具體配置如下

var webpack = require('webpack');
var path = require('path');

module.exports = function(env) {
    return {
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                names: ['vendor', 'manifest'] // Specify the common bundle's name.
            })
        ]
    }
};

使用上面的配置,將會生成三個bundles,vendor,main,manifest三個bundles。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容