携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
相信很多小伙伴或多或少都涉猎过性能优化,网上的性能优化八股文滚瓜烂熟,合并请求减少请求、减少dom结点多使用css3、合理压缩使用缓存等等,然后按着教程一顿操作猛如虎,满怀期待的试运行,最终发现效果甚微。其实对于中小型项目来说,这些常规的优化脚手架(vueCLi)里都配置好了,你在去配置就显得事倍功半了。我最近在写自己低代码项目的时候发现,打包出的vendors接近2M,由于我用的服务器配置不太好,带宽1M,请求这个js需要8~9秒,就着手想着去做优化,找了很多webpack优化教程看,跟着一个up视频(近几个月发布的)教程一步步优化,花了半天时间最后都没有出现什么跃进式的效果,文档上已经注明是webpack默认配置,但他还要演练实操,闭口没提是否是默认配置,真是为了讲而讲。
开源低代码平台
我最近两个月写的低代码平台
问题表现
项目依赖: vue3 + webpack5 + elementPlus + echarts
可以从图中看到这个1.6M的js加载用了9秒,服务器带宽1M,白屏时间近10秒,由于服务器是自己买来学习的,所以没必要升级配置,想要优化就只能从这个js文件下手。
问题猜想和定位
起初我以为是分包问题,可能是没有做分包所有内容都集中到一个js上了,最后查看打包产物发现webpack默认做了分包。
element-plus考虑后续开发便捷使用是全引,echarts按需引入。
使用webpack-bundle-analyzer插件进行分析,element-plus和echarts占用空间最大,还有element/icon也占据不少空间。
尝试解决
1、对vendors进一步分包,将大文件拆分出去,打成单独的包。增加以下配置:
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vue: {
test: /[\/]node_modules[\/]vue(.*)?[\/]/,
name: 'chunk-vue',
priority: 10,
},
elementPlus: {
test: /[\/]node_modules[\/]element-plus[\/]/,
name: 'chunk-elementPlus',
priority: 9,
},
elementPlusIcon: {
test: /[\/]node_modules[\/]@element-plus[\/]icons-vue[\/]/,
name: 'chunk-elementIcon',
priority: 8,
},
echarts: {
test: /[\/]node_modules[\/]echarts[\/]/,
name: 'chunk-echarts',
priority: 7,
},
},
},
},
复制代码
将上面文件都拆出vendors,打包成js文件。
2、 重新打包结果
可以看到打包产物多出了我们拆出的4个js,vendors体积减少了四倍多。速度能变快多少,我们更新到服务器实测看看。
服务器实测
到这我以为访问速度有所改善,其实不然
直接上服务器实测图,从图中我们可以看出即使分包后文件体积变小了,但是服务器上请求速度还是很慢。
原因分析
环境: 1M带宽服务器,实际请求速度应该在200~300k左右
我们分包后生成四个300-600k的文件,这个四个文件并行请求服务器,那么200~300k的速度实际上是均分到每个并行请求里面的,所以即使文件变小了但是请求变多了,请求还是一样慢。
其他解决方案
- 减少文件体积,按需加载减少引用(最后再做这个吧,其实已经没有太多的操作空间,默认打包配置已将代码压缩,treeShaking等)
- CDN,据说存储到内容分发网络后,获取资源速度会快很多,具体实测看看
- 开启GZIP,这个需要 webpack 配置和服务器 nginx 配合使用,网上很多教程,配置简单收益高
CDN方案
- 部分内容上CDN,如只将echarts、elementPlus等第三方库上CDN,查了一些资料发现这是网上常用的方案
- 静态资源全上CDN,打包产物除了index.html外全上CDN,包括打包出的js/css/img等,问了朋友上家公司的方案
尝试CDN
尝试了好几个云服务平台都行不通,国内服务器使用CDN必须拥有通过备案的域名,去阿里云买了一个域名,域名实名需要时间,实名通过后须等等待3天信息同步才能备案,备案审核需要很长一段时间。经此,这个方案只能暂时作罢,等域名通过备案后再试试吧。
尝试GZIP
-
webpack
yarn add compression-webpack-plugin@6.1.1 --save configureWebpack: (config) => { // 开发环境不配置 if (process.env.NODE_ENV !== 'production') return; // 生产环境才去配置 return { plugins: [ new CompressionPlugin({ //此插件不能使用太高的版本,否则报错:TypeError: Cannot read property 'tapPromise' of undefined filename: '[path][base].gz', // 这种方式是默认的,多个文件压缩就有多个.gz文件,建议使用下方的写法 // filename: '[path].gz[query]', // 使得多个.gz文件合并成一个文件,这种方式压缩后的文件少,建议使用 algorithm: 'gzip', // 官方默认压缩算法也是gzip test: /.js$|.css$|.html$|.ttf$|.eot$|.woff$/, // 使用正则给匹配到的文件做压缩,这里是给html、css、js以及字体(.ttf和.woff和.eot)做压缩 threshold: 10240, //以字节为单位压缩超过此大小的文件,使用默认值10240吧 minRatio: 0.8, // 最小压缩比率,官方默认0.8 //是否删除原有静态资源文件,即只保留压缩后的.gz文件,建议这个置为false,还保留源文件。以防: // 假如出现访问.gz文件访问不到的时候,还可以访问源文件双重保障 deleteOriginalAssets: false, }), ], }; }, 复制代码
-
nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/web/mobile-maker/packages/front/dist;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
# ......
# 以下为gzip配置
gzip on; # 开启gzip压缩
gzip_min_length 4k; # 小于4k的文件不会被压缩,大于4k的文件才会去压缩
gzip_buffers 16 8k; # 处理请求压缩的缓冲区数量和大小,比如8k为单位申请16倍内存空间;使用默认即可,不用修改
gzip_http_version 1.1; # 早期版本http不支持,指定默认兼容,不用修改
gzip_comp_level 2; # gzip 压缩级别,1-9,理论上数字越大压缩的越好,也越占用CPU时间。实际上超过2的再压缩,只能压缩一点点了,但是cpu确是有点浪费。因为2就够用了
# 压缩的文件类型 MIME类型
gzip_types text/plain application/x-javascript application/javascript text/javascript text/css application/xml application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/x-woff font/ttf;
gzip_vary on; # 是否在http header中添加Vary: Accept-Encoding,一般情况下建议开启
}
复制代码
服务器实测
gzip开启成功,效果很明显,访问速度相比之前快了很多。
- vendors体积:1739k => 561k
- 请求时间:9.28s => 2.68s
相比之前白屏时间确实是缩短了很多,但是这个白屏时间还是过长的。
代码优化
当前:echarts按需引入、element-plus全引
需要将element-plus改成自动引入,是自动引入而不是以前按需引入的写法,这个真的方便很多,要改的代码很少。
npm install -D unplugin-vue-components unplugin-auto-import
// webpack配置里加入下面配置
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
复制代码
main.js 里注册使用element-plus的代码删掉即可。
代码优化结果
优化效果也是相当明显的,vendors减少了300多k。
服务器实测
快了将近一秒,整体来说提升还是很大的。
总结
个人服务器1M带宽,也算是模拟一种恶劣环境吧,企业服务器得百兆千兆,极端环境优化完后再放到企业服务器,何尝不是一种提升呢
1、分包,没效果(服务器带宽就这么多,分成多个包,也是这些包均分带宽速度)
2、CDN,应该是最优的解吧(上CDN需要备案的域名,实名加备案需要很长时间,备案过了可以试试。上了CDN后走得是CDN服务器,静态资源直接从CDN服务器取,跟自己服务器没啥太大关系了,速度是质变。)
3、GZIP,效果很明显,体积能优化缩小3倍左右
4、项目优化,有效果(第三方库按需加载剔除不必要的引入)
vendors加载:
- 时间 - 从9.28秒到1.7秒
- 体积 - 1739K到431K(gzip)
本人第一次做首屏优化,经验浅薄,有更好方案的大佬,望能分享!