项目前端使用 Preact
笔者初次使用 webpack,尝试过从头配置,屡战屡败
最终选择,配置 preact.config.js,进行优化
前言
简单交代一下在 Preact 脚手架工具的基础上如何自定义配置:
-
已有的配置可参考 webpack-client-config.js
-
如何在 preact.config.js 中配置 webpack 文档传送门
-
Preact-cli 中的配置已安装 webpack-bundle-analyzer ,依据文档可以通过配置
// package.json
"scripts": {
...
"npab": "preact build --no-prerender --analyze"
}
进入正题!
情况概览
原先项目打包后,总文件大小为5.5MB
Fast3G下,首次加载时长平均在15秒-20秒
优化过程
问题一:bundle.js 过大
A计划:切分代码
Code Splitting,通过动态 import 的方式,减少页面初载时,所需加载资源的体积(按需加载)
React可使用:loadable-components;react-loadable 等
Preact可使用:preact-async-route 等
注:之前在实践时,使用的为 loadable-components,印象中是因 react-loadable 在使用过程中出现了警告,仅供参考。相关的讨论 => 传送门
B计划:去掉多余 import
太诡异了,哪来这么多 antd (无中生有 啊这…
排查代码后,会发现是多余的import在作祟。去掉之后,马上清爽了许多
问题二:代码分割待改进
原先的代码分割,业务代码和第三方模块你中有我,我中有你,容易出现:①重复加载相同的模块,②一方修改之后,整个的hash发生变化,影响缓存
这里使用SplitChunksPlugin,笔者的分割思路为:
- vendor: 常用第三方模块,使用频次较高
- antd:打包使用频次较高的部分,不全部单独打包,减少体积(这块首次加载肯定会载入
- moment:频次不高但也不低,比较大,但首次加载时不需载入
// preact.conf.js
export default {
webpack(config, env, helpers, options) {
config.optimization.splitChunks.chunks = "all";
config.optimization.splitChunks.minChunks = 4;
config.optimization.splitChunks.cacheGroups = {
antd: {
name: 'antd',
test: /antd|@ant-design/, // 匹配文件
priority: -10 // 优先级配置项
},
moment: {
name: 'moment',
test: /moment/,
minChunks: 3, // 共享模块最小块数
priority: -10
},
vendors: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
priority: -20 // 优先级配置项
}
}
},
}
打包完后,总文件大小为3.1MB
【日常疑问】第三方库分离后,首次加载所需时间反而增加了,该怎么平衡
第三方库分离后,意味着需要加载的文件变大了,导致时间不减反增(心态炸了
使用 Chrome 开发者工具中 Coverage 查看代码利用率后,疑惑更深,这不利用率更…??
前半个问题,通过平衡minChunks的大小,可以有一定改进(细微,细微…
再者,可以考虑使用CDN来进行优化,不在一棵树上吊死
后半个问题,查看一些成熟大型的网页首屏的代码利用率后,会发现这是正常的事情
想提高利用率的话,可以考虑优化业务代码,使用 Tree Shaking 减少业务代码等
(你问我咋没实践?啊这,因为用完后面的压缩,觉得挺好的,然后… 下次一定!
注: 因笔者为在原有配置上再定义,故省去了配置hash的步骤。hash的配置,有利于命中缓存,减少请求。其中,又分为 hash,chunkhash,及contenthash,三者的区别及具体的使用见后文参考链接。
问题三:文件都比较大
正在优化的项目比较大,所以用压缩,解压的时间换传输过程中的时间就很划算了。这里使用的压缩方案为 Gzip 传送门
Gzip 压缩背后的原理,是在一个文本文件中找出一些重复出现的字符串、临时替换它们,从而使整个文件变小
对于多媒体文件则没有必要采用Gzip,因为多数多媒体文件本身就是采用了有损压缩
对有损压缩的文件再进行 Gzip,效果不显著
法一:改 niginx/nginx.conf,设在http上
傻瓜操作,去掉其原有的所有#
// 开启或关闭gzip
gzip on;
// 是否在header中添加Accept-Encoding
gzip_vary on;
// 反向代理时是否启用压缩
gzip_proxied any;
// 压缩级别,越大,越好,越占CPU
gzip_comp_level 6;
// 压缩需要的缓冲区大小,此时为以8k为单位,申请16*8k
gzip_buffers 16 8k;
// 针对的协议版本
gzip_http_version 1.1;
// 进行压缩的文件最小字节数
gzip_min_length 1024;
// 压缩的文件类型
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
法二:改 sever 下的配置
server {
listen 3389;
server_name localhost;
location / {
root /var/www/finaldoc;
index index.html;
}
gzip on;
gzip_vary on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css application/javascript text/xml application/xml text/javascript;
}
配置完之后,不要忘记重启 Nginx => sudo service nginx restart
哦~! 这就是看孩子从不及格走向高分的快乐吗!(感动的热泪
总结
笔者就项目的情况,只实践了性能优化过程的几步
网上很多优秀的文章还提到了其他更多的优化方式,值得大家去实践
希望能对你有所帮助 ~
参考文章
优化路线
React 16 加载性能优化指南:整体的路线可参考
前端性能优化三部曲(加载篇):整体的路线可参考
前端性能优化原理与实践:详细的知识点介绍与梳理,推荐阅读
具体问题
Should I use react-loadable or loadable-components for code splitting?
Webpack 4 如何优雅打包缓存文件:3种 hash 的区分
项目不知道如何做性能优化?不妨试一下代码分割:Chrome 开发者工具中 Coverage 的使用
入门系列之在Nginx配置Gzip:修改 nginx.conf
工具
Lighthouse:文中评估页面性能的工具
网页性能分析不完全指南:使用 Chrome 开发者工具的 performance 面板分析运行时性能