从Webpack v4开始,移除了CommonsChunkPlugin
,取而代之的是SplitChunks
。最初,chunks(以及内部导入的模块)是通过内部Webpack图谱中的父子关系关联的。CommonsChunkPlugin曾被用来避免他们之间的重复依赖,但是不可能再做进一步的优化。
SplitChunksPlugin开箱即用,对于大部分用户来说非常友好。默认情况下,webpack 将根据以下条件自动拆分 chunks:
- 新的chunk可以被共享,或者模块来自于
node_modules
文件夹 - 新的chunk体积大于30kb(在进行 min+gz 之前的体积)
- 当按需加载chunks时,并行请求的最大数量小于或等于5
- 当加载初始化页面时,并发请求的最大数量小于或等于3
下面这个配置对象代表SplitChunksPlugin的默认行为。
module.exports = { //... optimization: { splitChunks: { chunks: 'async', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } };
大家可以从Github上下载示例代码。下面实例我们d Vue cli工程中使用了Echarts、Element-ui这些比较重和UI库。
如上图,默认webpack下自动生成了chunk-vendors.js、chunk-vendors.css和app.js三个bundle。这是因为maxInitialRequests(入口点的最大并行请求数)默认为3,它们的体积大于30kb。如果改成1,vendor这个chunk会合并到app中。如下图:
如果我们用到的依赖库存很小,可以通过减小
maxAsyncRequests
值来合并所有的chunk从而减小bundle数量,一定程序上通过减少Http请求来提高Web性能。
所有常见模块和vendor合并为一个chunk。这可能会导致更大的初始下载量并减慢页面加载速度。因此我们要找到减少文件大小和减少Http请求之间的平衡。随着现代浏览器逐渐支持http2,减少Http请求已经变得不那么重要了。因此,最佳实践是将大体积bundle分包成多个bundle来提高Web性能。在用Webpack打包时,如果chunk文件大于244 KB,会给出可能影响Web性能的警告。如果是3G以上的网络,1M以内也应该是可以的。显然本实例中1.5M太大了,因此我们要将Echarts、Element-ui分成单独的chunk。可以通过设置cacheGroups
缓存组来实现。
将maxAsyncRequests
设置成5,并做如下cacheGroups配置:
cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendor', priority: 10, chunks: 'initial', // only package third parties that are initially dependent }, echarts: { name: 'echarts', // split elementUI into a single package priority: 30, // the weight needs to be larger or it will be packaged into libs or app test: /[\\/]node_modules[\\/]echarts/, chunks: 'all' }, elementUI: { name: 'element-ui', priority: 30, test: /[\\/]node_modules[\\/]_?element-ui(.*)/, chunks: 'all' } }
分包效果如下图:
可以看到Echarts、Element-ui已经从先前的chunk-vendors中分离出来。
Echarts本身就很大,即使使用按需引入组件也有700多KB。Element-ui也是按需引入的,但js和css都很大,得进一步处理。
splitChunks.可以继承和/或覆盖来自splitChunks.* 的任何选项。但是
test
、priority
和reuseExistingChunk
只能在缓存组级别上进行配置。将它们设置为 false以禁用任何默认缓存组。
一个模块可以属于多个缓存组。优化将优先考虑具有更高priority(优先级)的缓存组。默认组的优先级为负,以允许自定义组获得更高的优先级(自定义组的默认值为 0)
1、在Vue cli工程中按需引入Element-ui组件,可以使用babel-plugin-component
插件。
npm i -D babel-plugin-component
2、在babel.config.js
指定styleLibraryName
路径为自定义主题相对于.babelrc
的路径,注意要加~。
{ "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "~theme" } ] ] }
3、安装chalk主题,可以从npm安装或者从GitHub拉取最新代码。
# 从 npm npm i element-theme-chalk -D # 从 GitHub npm i https://github.com/ElementUI/theme-chalk -D
4、修改var.scss
文件中的$--color-primary
变量值为#008080自定义主题。
也只可以直接新建element-variables.scss文件,用新的主题颜色变量覆盖默认主题颜色。但Element UI组件样式会被两次打包,一次是默认的样式,一次是覆盖的样式。所以需要用到Element ui主题工具进行深层次的纯净主题定制,最简单的简单的办法是按需引入样式并在
babel.config.js
中将styleLibraryName
指向自定义样式目录。
5、再次build可以看到Element UI的文件大小正确了。如下图:
另外,要让该工程兼容IE的话,得设置transpileDependencies:
transpileDependencies: [ 'vue-echarts', 'resize-detector', 'vue-baidu-map' ]
参考资料:https://v4.webpack.js.org/plugins/split-chunks-plugin/