Webpack Code Splitting - Libraries

Code Splitting - Libraries

文档地址
应用程序一般会使用第三方的类库,这些类库一般不会经常变动。
而我们的业务代码需要随着业务改变经常更新。
webapp为了提升效率,会根据cache header中的参数对文件进行缓存,
文件缓存之后就不需要再从cdn上从新拉去资源了。
为了使用缓存特性,我们需要将vendor文件进行缓存,无论我们的业务代码如何改变,
都不希望重新下载不变的vendor文件。
我们可以通过将代码分离成vendor bundle和application bundle来使用该特性。

单入口配置

不拆分的配置方法,比如我们在应用中使用(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,会发现momentindex.js被打包到了同一个文件中(bundle.js)。

上面的方案,对于应用来讲,是不完美的,如果index.js代码变了,那涉及到的bundle,都会进行重新编译。浏览器会重新加载所有的bundle,虽然很多bundle没有改变。

多入口配置(Multiple Entries)

momentvendor分离,实现更改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中都会出现moment.
这样配置没有实现我们的预期。为了解决这个问题,需要使用CommonsChunkPlugin

CommonsChunkPlugin

该plugin有些复杂,使用该plugin可以将不同bundle中的公共模块抽出来放在公用的bundle中。
如果该公用的bundle不存在,会创建一个新的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.
            })
        ]
    }
}

经过上面的配置,执行webpack,查看打包的bundle,moment代码只会存在于vendor bundle。
这样对index.js的修改,就不会导致全部文件进行重新打包了。

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进行了拆分。
但是我们观察到,当业务代码改变后,vendor bundle也会进行改变。这样我们就仍然无法使用浏览器的缓存功能。
产生这种情况是因为每次构建,webpack都会生成一些webpack的运行时代码(runtime code),
webpack需要依赖runtime code才能真正的向用户提供访问的内容。
当仅有一个单独bundle时,runtime code会包含与该bundle中。
但是当生成多个bundles时,runtime code会呗抽取到公用的module(此处位vendor文件)
由于是抽取到了vendor中,所以业务代码改变,仍然会影响vendor。

为了避免这个问题,需要将runtime代码拆分到一个单独的manifest文件,
虽然这样做会导致多生成一个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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容