资讯专栏INFORMATION COLUMN

Webpack CommonsChunkPlugin 理解

YJNldm / 3496人阅读

摘要:未定义时使用作为文件名。表示公共创建所需要的所有模块的最小体积。如果设置为,公共的所有子模块将会被选中。使用来命名文件,实现文件缓存的功能。当文件内容发生变化,文件名会随之改变。代码中再次使用了,从中提取出了名为的运行时代码。

CommonsChunkPlugin配置简介

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

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

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

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

配置项

首先贴一下文档。

{
  name: "string",
  names: "string[]",
  filename: "string",
  minChunks: "number|Infinity|function(module, count) -> boolean",
  chunks: "string[]",
  children: "boolean",
  async: "boolean|string",
  minSize: "number"
}

name和names:chunk的名称,如果这个chunk已经在entry中定义,该chunk会被直接提取;如果没有定义,则生成一个空的chunk来提取其他所有chunk的公共代码。

filename:可以指定提取出的公共代码的文件名称,可以使用output配置项中文件名的占位符。未定义时使用name作为文件名。

chunks:可以指定要提取公共模块的源chunks,指定的chunk必须是公共chunk的子模块,如果没有指定则使用所有entry中定义的入口chunk。

minChunks:在一个模块被提取到公共chunk之前,它必须被最少minChunks个chunk所包含(通俗的说就是一个模块至少要被minChunks个模块所引用,才能被提取到公共模块。)。minChunks参数有三点需要说明:

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

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

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

minSize:表示公共chunk创建所需要的所有模块的最小体积。

async:如果设置为true,一个异步的公共chunk将会作为options.name的子块和options.chunks的兄弟块被创建。该chunk会与options.chunks并行加载。你也可以使用该参数指定输出的文件名。

children:如果设置为true,公共chunk的所有子模块将会被选中。

例子

我们看一个简单的例子。

module.exports = {
    entry: {
        app: "./src/index.js",
        vender: [
            "lodash",
            "otherlib"
        ]
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: "vender"
        })
    ],
    output: {
        // 使用Hash来命名文件,实现文件缓存的功能。当文件内容发生变化,文件名会随之改变。
        filename: "[name].[chunkhash].js", 
        path: path.resolve(__dirname, "dist")
    }
};

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

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

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

解决方案有以下几种:

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

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

将runtime部分的代码提取到一个多带带的文件中,代码如下。

module.exports = {
    entry: {
        app: "./src/index.js",
        vender: [
            "lodash"
        ]
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: "vender",
            minChunks: Infinity
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest",
            chunks: ["vender"]
        })
    ],
    output: {
        filename: "[name].[chunkhash].js",
        path: path.resolve(__dirname, "dist")
    }
};

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

分析Vue的使用方式

Vue在production模式中使用如下配置

// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
  name: "vendor",
  minChunks: function (module, count) {
    // any required modules inside node_modules are extracted to vendor
    return (
      module.resource &&
      /.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, "../node_modules")
      ) === 0
    )
  }
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
  name: "manifest",
  chunks: ["vendor"]
})
自定义minChunks

minChunks配置项有两个参数,module为当前要提取的源chunk中所包含的模块,count表示模块的个数。
自定义函数会被循环调用,直到遍历完所有模块。

module.resource为模块的绝对路径,所以这段代码判断了模块是否在node_modules下,是的话则打包到vender中。

后面一个CommonsChunkPlugin从vender中提取了运行时代码,避免每次打包vender的Hash值都发生变化导致缓存无效。

如有问题,欢迎指正。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89000.html

相关文章

  • Webpack 4.0 CommonsChunkPlugin 和 optimization spli

    摘要:可以通过配置属性进行修改,默认将会自动创建个库文件仅含有依然会创建个库文件仅含有假设所有的体积都大于将会创建一个库文件和一个通用组件文件仅含有当这些体积小于是,会故意将该模块复制到三个文件中。 该文章内容大致翻译自 webpack 4: Code Splitting, chunk graph and the splitChunks optimization 原有的问题 webpack...

    Caizhenhao 评论0 收藏0
  • 从零开始的webpack生活-0x007:CommonsChunkPlugin基本用法

    摘要:概述上一章讲的是,和这一章依旧没有丝毫关系,这一章讲的是说实在的,这个插件略复杂,我还没完全搞懂,大概是还没到那么深我就已经选择其他解决方案了吧,所以这里只讲一些基本用法。直接打包几个包当然还有许多更加复杂的用法,还请看关于章节资源源代码 0x001 概述 上一章讲的是providerPlugin,和这一章依旧没有丝毫关系,这一章讲的是CommonsChunkPlugin,说实在的,这...

    Sleepy 评论0 收藏0
  • 前端临床手札——webpack构建逐步解构(下)

    摘要:续前端临床手札构建逐步解构上工作流程案例最近添加了雪碧图功能,并把替换成的,详细可以看分支构建生产上一篇说完了本地测试和是如何工作,接下来分析构建生产模式下配置如何配置和每个模块干了什么。 续 前端临床手札——webpack构建逐步解构(上) 工作流程 showImg(https://segmentfault.com/img/bVCXjo?w=793&h=410); 案例:multip...

    TerryCai 评论0 收藏0
  • webpack.optimize.CommonsChunkPlugin的minChunks解析

    摘要:,顾名思义,是用来把公用模块打包到一起的插件,以减小打包后文件的体积。令人迷惑的中文社区和官网都对此属性语焉不详。官网的解释我实在看不懂在被放到共同之前需要包含模块的的最小数量。当大于等于设定的值时,该模块就会被打包到公用包中。 CommonsChunkPlugin, 顾名思义,是用来把公用模块打包到一起的插件,以减小打包后js文件的体积。 令人迷惑的minChunks 中文社区和官网...

    lavor 评论0 收藏0
  • webpack: 从指定入口文件中提取公共文件

    摘要:通过函数,指定三个入口文件为,同时我们还要设置为,表示指定三个入口文件中提取出的公共文件,最少要被三个不同的入口文件引用。所以就是从三个入口文件中提取公共的文件。从两个公共文件中,再提取公共部分先说一下,这是什么意思有个公共文件。 在不明白CommonsChunkPlugin的使用情况下,直接上手webpack4的splitChunks,实在是难上加难。为了能更好的理解splitChu...

    tuomao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<