事实上, 只有10%-20%的最终用户响应时间是发在从Web服务器获取HTML文档并传送到浏览器中的。 如果希望能够有效地减少页面的响应时间,就必须关注剩余80%-90%的最终用户体验。 –Steve Souders
大家好,前端性能优化是一个非常重要的问题,首屏时间长短,直接影响到用户的体验与留存。本文介绍一下优化过程的心路和历程。最终从2000ms优化到148ms。
一、项目技术栈
框架:Vue2
打包工具:webpack
二、优化方法
1.代码压缩
gzip压缩可以节省50%-70%的网络开销
浏览器支持的压缩类型可以通过network的Accept-Encoding: gzip, deflate来查看。支持deflate的浏览器也支持gzip,但很多浏览器支持gzip却不支持deflate,因此gzip是最理想的压缩方法。
// webpack中配置如下: const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = ["js", "css", "html"]
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require("compression-webpack-plugin");
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\.(" + config.build.productionGzipExtensions.join("|") + ")$"
),
threshold: 10240,
minRatio: 0.8
})
);
}
// nginx 中配置
gzip on; # 开启Gzip
gzip_static on; # 开启静态文件压缩
gzip_min_length 1k; # 不压缩临界值,大于1K的才压缩
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss; # 进行压缩的文件类型
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6].";
开启gzip一定要前后单同时操作才有效!!!
F12打开浏览器控制台-network,成功!
2.配置sourceMap
productionSourceMap: false,
关掉sourceMap
3.使用CDN内容分发网络
在index.html
文件中通过环境来判断是否引入cdn文件,webpack通过环境判断是否使用cdn引入文件的全局变量。
只需在刚刚配置gzip的代码加上一段代码即可:
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require("compression-webpack-plugin");
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\.(" + config.build.productionGzipExtensions.join("|") + ")$"
),
threshold: 10240,
minRatio: 0.8
})
);
// 配置externals就是当使用CDN进入的js文件在当前项目中可以引用
// 比如在开发环境引入的vue是import Vue from 'vue', 这个大写的Vue就是对应的下面的大写的Vue
webpackConfig.externals = {
vue: "Vue",
"vue-router": "VueRouter",
axios: "axios"
};
}
在html中引入这段代码,使用EJS语法判断是否为生产环境,引入:
<body>
<div id="app"></div>
<% if (process.env.NODE_ENV === 'production') { %>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
<% } %>
</body>
同时去掉所有的import和Vue.use()
// import Vue from 'vue'
// import Router from "vue-router";
// Vue.use(Router);
F12打开浏览器控制台-network,引入cdn成功!
4.将图片打包上传至七牛云
有些图片实在是过大,影响了资源加载的时间,故将其打包上传至七牛云或者阿里云oss对象存储中,这样页面中用不到图片的时候,就不加载,减轻了首屏资源加载的压力。
5.去除首屏不需要的依赖
可以看到,首屏大文件是elementUI,elementUI采用部分引入,故最后只有48kb,其实是lodash,但排查发现,全局只使用了一次lodash,故不在app.js中全局引入,在使用的地方引入即可。
去除lodash后如下,首页所需加载的依赖减小至82kb左右,是可以接受的范围。
6.其他
- 压缩图片,推荐工具:https://tinypng.com/
- 路由懒加载:需要在router里配置,这样触发某条路由,再去加载对应的资源,减少首屏压力
- 优化后端接口:首屏的接口如果有特别耗时的,那么就需要去优化后端了,比如本文对首页的热点数据使用了redis缓存,速度更快。
- elementUI按需加载(这里有个存疑,我的element按需加载后是80kb,但也采用过cdn方案,目前两者性能相差无异)
- SSR?没有去实践,正值期末考试,以后再尝试吧~
最后打包分析,可以看见依赖已经非常小了,网站肉眼可见的快了~
三、总结
因为本项目是将vue、vuex、vue-router、axios、element-ui都放到了bootCDN上,所以资源加载取决于cdn的快慢,所以成绩一直不是很稳定,各位大佬轻喷。
服务器是位于上海的阿里云服务器,前后端单体部署。
榜中的最好成绩是cdn比较快的时候,146ms,平时大部分稳定在200-400ms,还是取决于cdn网速和到服务器的距离。
目前网站经过一系列优化后,速度不如巅峰时期了,我也改不回去了......