26
本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006871991
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang

前言

与单页应用相比,多页应用存在多个入口(每个页面即一个入口),每一个入口(页面)都意味着一套完整的js代码(包括业务逻辑和加载的第三方库/框架等)。
在上一篇文章(webpack多页应用架构系列(二):webpack配置常用部分有哪些?)中,我介绍了如何配置多页应用的入口(entry),然而,如果仅仅如此操作,带来的后果就是,打包生成出来的每一个入口文件都会完整包含所有代码。
你也许会说:"咱们以前写页面不也是每个页面都会加载所有的代码吗?浏览器会缓存,没事的啦"。其实问题在于,以前写代码都是单个单个js来加载的,一个页面加载下来的确所有页面都能共享到缓存;而到了webpack这场景,由于对于每一个页面来说,所有的js代码都打包成唯一一个js文件了,而浏览器是无法分辨出该文件内的公共代码并加以缓存的,所以,浏览器就没办法实现公共代码在页面间的缓存了(当前页面的缓存还是OK的,也就是说刷新不需要重新加载)。

想智能判断并打包公共代码?CommonsChunkPlugin能帮到你

CommonsChunkPlugin的效果是:在你的多个页面(入口)所引用的代码中,找出其中满足条件(被多少个页面引用过)的代码段,判定为公共代码并打包成一个独立的js文件。至此,你只需要在每个页面都加载这个公共代码的js文件,就可以既保持代码的完整性,又不会重复下载公共代码了(多个页面间会共享此文件的缓存)。

再提一下使用Plugin的方法

大部分Plugin的使用方法都有一个固定的套路:

  1. 利用Plugin的初始方法并传入Plugin预设的参数进行初始化,生成一个实例。
  2. 将此实例插入到webpack配置文件中的plugins参数(数组类型)里即可。

CommonsChunkPlugin的初始化常用参数有哪些?

  • name,给这个包含公共代码的chunk命个名(唯一标识)。
  • filename,如何命名打包后生产的js文件,也是可以用上[name][hash][chunkhash]这些变量的啦(具体是什么意思,请看我上一篇文章中关于filename的那一节)。
  • minChunks,公共代码的判断标准:某个js模块被多少个chunk加载了才算是公共代码。
  • chunks,表示需要在哪些chunk(也可以理解为webpack配置中entry的每一项)里寻找公共代码进行打包。不设置此参数则默认提取范围为所有的chunk。

实例分析

实例来自于我的脚手架项目webpack-seed,我是这样初始化一个CommonsChunkPlugin的实例:

  var commonsChunkPlugin = new webpack.optimize.CommonsChunkPlugin({
    name: 'commons', // 这公共代码的chunk名为'commons'
    filename: '[name].bundle.js', // 生成后的文件名,虽说用了[name],但实际上就是'commons.bundle.js'了
    minChunks: 4, // 设定要有4个chunk(即4个页面)加载的js模块才会被纳入公共代码。这数目自己考虑吧,我认为3-5比较合适。
  });

最终生成文件的路径是根据webpack配置中的ouput.path和上面CommonsChunkPlugin的filename参数来拼的,因此想控制目录结构的,直接在filename参数里动手脚即可,例如:filename: 'commons/[name].bundle.js'

总结

整体来说,这套方案还是相当简单的,而从效果上说,也算是比较均衡的,比较适合项目初期使用。最近我也得到了打包公共代码的其它思路,相对于本文来说算是进阶版的吧,但是维护成本相对应也提高了,待我试用后再写文介绍给大家。

示例代码

诸位看本系列文章,搭配我在Github上的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)

附系列文章目录(同步更新)

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006871991
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang

如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

10 条评论
youkelike · 2017-03-02

CommonsChunkPlugin被这个插件的参数困扰到了,经过测试后发现:
1、至少要提供name参数,filename不提供的话默认值就是[name].js
2、如果给的name参数的值是不存在的chunk,则filename的值不能与现有的chunk名字重复,否则会报错
3、如果给的name参数的值是现有chunk名(entry.key中的某一个),就会提取共有代码放到同名的入口文件中

+2 回复

kria · 2017-11-27

你好 想问一下你有没有试过在CommonsChunkPlugin中提取出less的公共部分。我配置好了less/css的loader,配置了ExtractTextPlugin,less和css都能提取到单独的文件里。我希望能把多个入口的less部分提取到一个单独的文件里。我发现当我配置CommonsChunkPlugin好之后,css的公共部分的确被整合提取到了一个文件里,但是多次引用的less部分并没有被提取,各个入口单独的css部分还是存在着重复的代码(公共的less编译的css部分)。折腾了挺久也没有搞出来,想请教一下

+1 回复

0

跟css和less什么的都没有关系,webpack只关心js,因此在公共的js文件里引用的css/less就会被打包到一起,而反之则独立出来

array_huang 作者 · 2017-11-28
0

@array_huang 我也是这样理解的,但是实践发现CommonsChunkPlugin确实会隐性的把多个入口中重复引入的css也单独打包到一个文件下。然后我就在想既然css可以,那less应该也可以。然后实践之后有了上面的问题。
就是【多个入口中,重复引用的css确实被提取出来到了common.css里,但重复引用的less文件在打包编译之后,并没有被提取到common.css中,还是分别存在各个业务模块下的css里。】
但是这个问题我昨天晚上已经解决了。这里面主要是CommonsChunkPlugin 和CommonsChunkPlugin 的配合使用。我通过配置 CommonsChunkPlugin 的 minChunks,
以及 ExtractTextPlugin 的 allChunks 为 true ,成功的把重复的less部分提取到了一个css文件下。这个点,官网虽然写了,但是写得不是很明确。这两个属性是有关联的,单独只写其中一个,都解决不了我的这个问题。

kria · 2017-11-28
老徐不二 · 2016-09-18

CSS的公共模块如何提取

回复

array_huang 作者 · 2016-09-18

CSS没法自动提的,只能够是自己安排好目录,在公共的js来require公共的css,看我这篇文章《webpack多页应用架构系列(五):听说webpack连less/css也能打包?》https://segmentfault.com/a/11...

回复

earlyeearly · 2017-03-06

mark

回复

Be_Quiet_SS · 2017-05-03

你好,webpack给每个入口js文件定义了一个id,但是如果我新增一个入口文件,然后重新编译。就会打乱之前id的定义,导致全部文件都有修改,请问这个有什么方法可以避免呢?

回复

0

为了生成保存在构建中的标识符,webpack 提供了 NamedModulesPlugin(推荐用于开发模式)和 HashedModuleIdsPlugin(推荐用于生产模式)这两个插件。

array_huang 作者 · 2017-07-20
jh2k15 · 2018-05-07

4.7 SplitChunksPlugin

回复

载入中...