美文网首页程序员让前端飞
Webpack Code Splitting - Librari

Webpack Code Splitting - Librari

作者: yftx_ | 来源:发表于2017-03-03 16:50 被阅读49次

    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。

    相关文章

      网友评论

        本文标题:Webpack Code Splitting - Librari

        本文链接:https://www.haomeiwen.com/subject/oddrgttx.html