前些日子,项目在发包的时候失败了,竟然是因为构建产物太大导致的,而我又对这块可以说是完全不了解了,出于好奇心和学习的心态,开始尝试优化一下这个项目,在请教了大佬之后,又在 webpack 官网以及掘金等学习网站查阅了大量资料后,开始上手。
先启用 webpack-bundle-analyzer 查看打包体积。(这是一个查看构建产物体积树图的插件,非常好用,安装之后在 webpack 的 plugins 下使用)
一眼看去,体积惊人,而且充斥着大量的 less 代码,首先想到的是应该拆分 css。
于是开始使用 webpack 官方开箱可用的 mini-css-extract-plugin 插件来进行拆分 css。
使用起来也是非常方便,在同样的 webpack 的插件配置里
(命名规则可查看官方文档)
使用之后,再次运行构建,发现还是13.8 MB,完全没有变化,这就很令人头秃。
一番搜索之后,原来是忽略了使用这个插件最重要的一步:配置 loader
学习了官网后,我按图索骥配置了一番,在经历一些挫折(style-loader 和 MiniCssExtractPlugin.loader 不能混用!如果混用会出现报错)之后,终于成功的分离出来了
本以为分离的事告一段落,然后随手看了下构建产物的大小
22 MB.。。我这是整了个负优化吗?不应该呀,确定分离 css 是正确的实践。
点进去查看文件夹体积才发现,css 文件超大
这显然是不合理的,随便点开一个 css 后看到一行接着一行,这才恍然大悟,原来还需要手动压缩呀(这里还是因为不仔细看官方文档)
又是一番查看文档
又是一番 copy(注意,这里的插件是放在优化 optimization 这一栏里),然后再次执行构建
css 文件体积大幅度减小。
这一套操作下来,体积来到了 12.3 MB,减小是减小了,但是感觉还是和预期相差很大,这个项目的体量不该有这么大的。
于是乎查看构建的 js 文件
发现 好多文件里都存在一个叫 @tencent/omui/dist 的包(omui 组件库,团队大佬封装的 react 组件库),这显然是重复打包了,又是一番搜索后,锁定到了 webpack 配置中 optization 里的 splitChunks 中
这个配置讲解的文章很多,例如 如何使用 splitChunks 精细控制代码分割 - 掘金 (juejin.cn)
这里配置就可以根据项目来自由配置了,我选择直接先干掉现有的配置,使用默认的
(现有配置)
(官方默认配置)
干掉之后再次构建
代码体积光速下降到了 2.14 MB,整体上大的改动基本就没了,后续就是针对部分细节进行小的优化
比如左下角两张 png,在项目里完全可以使用 cdn 的形式替代,比如 lodash 的按需加载,或者一些模块采用外部导入 externals,这里就不再过多赘述,根据项目实际情况自行优化
由于项目是服务端渲染的,所以使用到 webpack-manifest-plugin 这个插件,插件会生成一个资源和路径的映射
css 也很很贴心的自动生成了映射放在构建产物文件夹中,所以这里就不用管。
接下来改一下接入层 view 渲染的 ejs 模板就好,在 ejs 里引入上传好的 main.css 样式就可以了。
然后在测试环境先看看优化后的提升,这里随便打开一个页面来对比分离前后的变化
可以看到,未分离的资源加载是只有 js 文件,没有 css,大小在 3.9 MB
下面打开分离后的资源加载
可以看到,分离后的资源加载 css + js 大小是3.5 MB,也比分离前的要小,而且切换页面更有种“按需加载”的酸爽感
但是只有0.4 MB的优化,并不能达到预期呀。
当我点开这些加载的 css 文件发现,每个 css 文件里竟然都有大量重复的样式代码,看来是重复打包,观察到样式来源都是 mixin 的样式
后续解决方案是给这些 mixin 样式加上括号(如图最上方的样式)就可以避免重复打包的问题
(原理如图所示)
再次构建。
css 构建产物只剩 558 KB!大大减少资源的使用
后续还有一些小改动,比如 放弃使用 awesome-typescript-loader(已经不维护了,而且不够统一) ,直接使用 babel-loader 来打包 ts 文件
使用 fork-ts-checker-webpack-plugin 来单独进行 ts 校验,加快构建速度
开启 webpack5 的 cache,构建速度有了缓存之后大幅度提升
cache: {
type: 'filesystem',
buildDependencies: {
config: [
__filename,
],
},
},
(基于文件系统的缓存配置)
到这里,这波构建优化基本就算完成了,构建产物也从13.8 MB 优化到了 2.12 MB.
构建速度也有大幅度提升
中间还和大佬讨论了一波“拆分 css 会不会对模块联邦造成影响”的问题,后来经过测试,是不会有影响的,模块联邦导出的组件会带有打包的样式。
最后,这次优化操作都是些很常规的操作,在很多优化教程和文档里都有提到, 但是涉及到的一些细节还是值得注意的,比如到现在我也不太明白为什么这个项目离原有的 splitChunks 配置会引起 omui 重复打包那么多次的问题,以及自己尝试独特配置这个的时候,打包没问题,但是页面会出现白屏的问题,后续也会再研究研究相关配置,splitChunks 还是很香的。。