记录一次前端优化企业项目
记录一次前端优化企业项目
随着部门项目业务功能越来越多,发现打包速度慢、体积较大,想着能否针对 webpack 做优化。
优化打包速度
首先要找一个衡量速度的工具,webpack 插件speed-measure-webpack-plugin
,可以测量所有 loader 花费的时间。
1 |
|
然后执行yarn build
,等待一会出结果。
从图中可以看出,babel-loader、less-loader
执行时间较长,另外还有 eslint-loader
,由于平时开发中编辑器都开启了 eslint 功能,另外在代码提交的时候有 pre-commit
也会做检测,由于项目过大每次打包都要让eslint-loader
全量检测一遍,属实浪费时间性能,因此可以去掉,另外 2 个 loader 执行时间长,可能匹配内容过多,浪费不必要的搜索。
优化 loader
从这两个角度出发,首先去掉eslint-loader
,然后优化其他 loader 的匹配规则。
项目中使用的.less、.js、.jsx,在源码中发现:
- 存在不必要的 loader,例如 sass-loader 等项目用不到的类型文件,需要去掉。
- 匹配了很多不需要匹配的文件后缀名,所以来说其他 loader 匹配文件都是浪费搜索性能的。
1 |
|
时间从 287s 优化到 119s,速度提升了 58%。
优化体积
首先使用 webpack 插件webpack-bundle-analyzer
分析各个包打包后的体积。
1 |
|
打包后发现第三方库moment、echarts、ant design、lodash
体积比较大。
- moment 体积大是因为把本地化内容页打包了。
- Echarts 所有图形都打包了,其实只需要打包项目中用到的图的类型。
- ant design 体积过大,由于时间控件内部采用 moment,应该替换成 dayjs。
- lodash 默认打包了所有功能函数。
优化 moment
使用IgnorePlugin
忽略指定目录,moment
会将所有本地化内容和核心功能一起打包,可以使用这个插件忽略本地化内容,在使用的时候再引入。
1 |
|
优化前后差别:
从图可以看出优化挺大的,264kb 到 60kb,体积减少了 77%。
优化 Echarts
用到什么类型图表,就引入什么类型的,没必要所有一并引入。
1 |
|
优化前,由图可以看出打包了所有图表类型
优化后
从 5.35m 优化到 253kb。
优化 ant design
在使用 Time-Picker 等时间控件的时候,默认使用的 moment,体积比较大,参考官网可以替换成 days.js。
1 |
|
尝试过发现并没有看出 ant design 体积变化差异很大,不过这也是一种优化的方向。
优化 lodash
目前采用lodash
包,应该需要使用lodash-es
模块化版本,支持 tree-shaking,可以减少打包体积。
不过目前项目都是用 lodash
,并且没有单独使用函数,例如:import cloneDeep from 'lodash/cloneDeep'
,由于使用地方比较多,也不能每个页面都检查,所以打算采用lodash-webpack-plugin + babel-plugin-lodash
两个 webpack 插件。
babel-plugin-lodash
可以自动将 lodash 函数按需引入。webpack-lodash-plugin
去掉多余的功能代码,进一步减少体积。
1 |
|
配置 webpack
1 |
|
优化前后差别:
lodash 体积从 97kb 优化到 13kb,缩小了 86%的体积。
代码打包分块
使用代码分块之前,涉及到两个知识点:
- 代码分离(Code Splitting):动态加载代码,在需要的时候再来加载,例如路由懒加载。
- 打包分离(Bundle Splitting):主要是为更好的缓存,创建更多、更小的文件,可能很多页面共用了某一个模块功能,将其单独打包出来。
分包之前要考虑为什么要分包,能给项目带来什么优势?
- 代码分离:如果不用路由懒加载,那就是一开始进入页面就会加载所有业务模块,导致首屏渲染速度很慢。
- 打包分离:如果有一个体积很大的文件,只改了少量的代码,浏览器仍然要重新下载整个文件,如果分为两个或多个文件,浏览器只需要下载改动那个文件,其他未改动的部分从浏览器缓存中加载,可以提高加载速度。(所以来说代码分割提高访问速度,是与浏览器缓存息息相关。)
整体思路:需要怎么拆分,需要把不是每次都用到的依赖拆分出来,让其在使用的时候再根据页面按需加载。只有一个目的,就是要把用的比较少的公共依赖文件分割出来;引用次数较多的模块分割出来,避免每次都要重新加载那一部分代码。
着手操作:
- 将项目框架代码分割,基本每个页面都会用到,例如:React、Ract-dom、React-dom-router、React-redux 等。
- 将 Echarts 分割,目前了解到只有几个页面使用了图表,只需要访问指定页面再按需加载即可。
- 项目中业务组件,基本都会用到,也需要单独分割出来。
1 |
|
总结
- 打包分割是和浏览器的缓存机制存在联系的,主要是通过浏览器缓存没有变化的资源,提高加载速度。
- 开发代码中尽量少用
import * from 'xxx'
,没法进行 tree-shaking,导致打包体积变大。 - 对于时间的处理,尽量使用体积更小的 dayjs,而不是体积较大的 moment,如果必须要使用 moment,一定要对本地化配置做处理,减少打包体积。
- 对于
lodash
,尽量使用模块版本的lodash-es
,可以利用 tree-shaking,减少打包体积。