• Webpack CommonsChunkPlugin 理解


    最近读了一下webpack的文档,读到CommonsChunkPlugin这个插件,深深折服与webpack的强大,同时也产生了一些自己的疑问。

    首先,CommonsChunkPlugin这个插件是用来提取公共代码的,通过将公共模块提取出来,只在页面加载的时候引入一次,提升应用的加载效率。

    顺便提一下,chunk其实就是代码块的意思,可能是一个或多个模块,一般就是一个js文件。

    CommonsChunkPlugin有中文翻译的文档,但是感觉并不是很通顺,英文文档看完也有一些疑惑,比如minChunks到底是做什么用的,怎么用?chunks是什么?首先贴一下文档。

     1 {
     2   name: string, // or
     3   names: string[],
     4   // The chunk name of the commons chunk. An existing chunk can be selected by passing a name of an existing chunk.
     5   // If an array of strings is passed this is equal to invoking the plugin multiple times for each chunk name.
     6   // If omitted and `options.async` or `options.children` is set all chunks are used, otherwise `options.filename`
     7   // is used as chunk name.
     8   // When using `options.async` to create common chunks from other async chunks you must specify an entry-point
     9   // chunk name here instead of omitting the `option.name`.
    10 
    11   filename: string,
    12   // The filename template for the commons chunk. Can contain the same placeholders as `output.filename`.
    13   // If omitted the original filename is not modified (usually `output.filename` or `output.chunkFilename`).
    14   // This option is not permitted if you're using `options.async` as well, see below for more details.
    15 
    16   minChunks: number|Infinity|function(module, count) -> boolean,
    17   // The minimum number of chunks which need to contain a module before it's moved into the commons chunk.
    18   // The number must be greater than or equal 2 and lower than or equal to the number of chunks.
    19   // Passing `Infinity` just creates the commons chunk, but moves no modules into it.
    20   // By providing a `function` you can add custom logic. (Defaults to the number of chunks)
    21 
    22   chunks: string[],
    23   // Select the source chunks by chunk names. The chunk must be a child of the commons chunk.
    24   // If omitted all entry chunks are selected.
    25 
    26   children: boolean,
    27   // If `true` all children of the commons chunk are selected
    28 
    29   async: boolean|string,
    30   // If `true` a new async commons chunk is created as child of `options.name` and sibling of `options.chunks`.
    31   // It is loaded in parallel with `options.chunks`.
    32   // Instead of using `option.filename`, it is possible to change the name of the output file by providing
    33   // the desired string here instead of `true`.
    34 
    35   minSize: number,
    36   // Minimum size of all common module before a commons chunk is created.
    37 }
    • namenames:chunk的名称,如果这个chunk已经在entry中定义,该chunk会被直接提取;如果没有定义,则生成一个空的chunk来提取其他所有chunk的公共代码。
    • filename:可以指定提取出的公共代码的文件名称,可以使用output配置项中文件名的占位符。未定义时使用name作为文件名。
    • chunks:可以指定要提取公共模块的源chunks,指定的chunk必须是公共chunk的子模块,如果没有指定则使用所有entry中定义的入口chunk。
    • minChunks:在一个模块被提取到公共chunk之前,它必须被最少minChunks个chunk所包含。(通俗的说就是一个模块至少要被minChunks个模块所引用,才能被提取到公共模块。)

    该数字必须不小于2或者不大于chunks的个数。默认值等于chunks的个数。

    如果指定了Infinity,则创建一个公共chunk,但是不包含任何模块,内部是一些webpack生成的runtime代码和chunk自身包含的模块(如果chunk存在的话)。

    用户也可以定制自己的逻辑去生成代码。

    我们看一个简单的例子。

     1 module.exports = {
     2     entry: {
     3         app: './src/index.js',
     4         vender: [
     5             'lodash',
     6             'otherlib'
     7         ]
     8     },
     9     plugins: [
    10         new webpack.optimize.CommonsChunkPlugin({
    11             name: 'vender'
    12         })
    13     ],
    14     output: {
    15         filename: '[name].[chunkhash].js',     // 使用Hash来命名文件,实现文件缓存的功能。当文件内容发生变化,文件名会随之改变。
    16         path: path.resolve(__dirname, 'dist')
    17     }
    18 };

    上面的代码中定义了两个入口,app和vender(公共库),plugins中使用CommonsChunkPlugin提取vender。

    vender是我们提取出来的公共chunk,通常不会被修改,所以理应在每次编译后文件名保持一致。然而,我们尝试修改入口文件index.js会发现,vender的文件名会发生变化。

    原因呢上面提到过,由于每次编译会导致vender的module.id发生变化,内部的runtime代码随之发生改变。

    解决方案有以下几种:

      1. 使用NamedModulesPlugin插件,用文件路径而非默认的数字ID来作为模块标识。

      2. 使用HashedModuleIdsPlugin插件,用相对路径的Hash值来作为模块标识。推荐在生产环境中使用。

      3. 将runtime部分的代码提取到一个单独的文件中,代码如下。

     1 module.exports = {
     2     entry: {
     3         app: './src/index.js',
     4         vender: [
     5             'lodash'
     6         ]
     7     },
     8     plugins: [
     9         new webpack.optimize.CommonsChunkPlugin({
    10             name: 'vender',
    11             minChunks: Infinity
    12         }),
    13         new webpack.optimize.CommonsChunkPlugin({
    14             name: 'manifest',
    15             chunks: ['vender']
    16         })
    17     ],
    18     output: {
    19         filename: '[name].[chunkhash].js',
    20         path: path.resolve(__dirname, 'dist')
    21     }
    22 };

    代码中再次使用了CommonsChunkPlugin,从vender中提取出了名为manifest的运行时代码。

    未完待续,欢迎指正。

  • 相关阅读:
    Eclipse+Java+OpenCV246人脸识别
    Eclipse+Java+OpenCV246环境搭建和代码测试
    Request对象和Response对象详解
    request与response对象详述
    request对象和response对象
    减少HTTP请求之将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片(大型网站优化技术)
    base64码通过http传输 +号变 空格 问题解决
    RSA Android加密的数据服务器上无法解密?
    RSA解密时javax.crypto.BadPaddingException: Data must start with zero
    SRA解密报错:Data must start with zero
  • 原文地址:https://www.cnblogs.com/dong93/p/7655171.html
Copyright © 2020-2023  润新知