- 注:本文只适用于 vue-cli 初始化的项目或依赖于 webpack 打包的项目 *
首屏加载优化
背景:基于vue-cli3创建的项目编译后发布测试,发现有个文件chunk-vendors文件大小达到846kb,加载耗时达到7.38s左右,首屏白屏时间过长。
针对这个进行以下优化:
- 路由懒加载
这个我在项目里已经做到了,但是针对这个汇总再简单总结下
{
path: '/',
name: 'home',
component: () => import(/* webpackChunkName: "home" */ './views/home/index.vue'),
meta: { isShowHead: true }
}
我这里是结合ES 提出的 import
方法和webpack魔法注释 /* webpackChunkName: "group-foo" */
轻松实现路由懒加载
- 开启服务器Gzip
尽管第一步已经做到了,但仍然有846k的大小,所以需要继续优化。开启Gzip就是一种压缩技术,需要前端提供压缩包,然后在服务器开启压缩,文件在服务器压缩后传给浏览器,浏览器解压后进行再进行解析。
首先安装webpack提供的compression-webpack-plugin
进行压缩,然后在vue.config.js:
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = ['js', 'css']
......
plugins: [
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
})
]
....
然后在Nginx配置
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
此时我们再看chunk-vendors文件大小达到227k,耗时1.7s
- 启动CDN加速
我们继续采用cdn的方式来引入一些第三方资源,就可以缓解我们服务器的压力,原理是将我们的压力分给其他服务器点。
首先在index.html中:
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.3/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/element-ui/2.8.2/index.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.js"></script>
然后在vue.config.js中通过externals外部扩展,可以忽略不需要打包的库:
module.exports = {
......
configureWebpack: (config) => ({
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'axios': 'axios',
'element-ui': 'ElementUI'
}
})
......
}
main.js
import Vue from 'vue' // 下面有用到所以没注释
// import ElementUI from 'element-ui' // 注释
// import axios from 'axios' // 注释
store.js
// import Vue from 'vue' // 注释
// Vue.use(Vuex) // 注释
import Vuex from 'vuex'
router.js
// import Vue from 'vue' // 注释
// Vue.use(Router) // 注释
import Router from 'vue-router'
这个时候我们再来看下效果:
可以看到chunk-verdors文件已减小到20.9kb,耗时172ms,基本项目秒开无压力了。
- 其他优化点
——在vue.config.js中设置productionSourceMap:false这样打包后map文件就没了,map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。如果不需要的话可以这样操作。
——修改uglifyOptions去除console来减少文件大小,如果代码中打了很log,这个优化还是有点效果的。
代码层面优化
针对vue项目代码层面优化就得回归到.vue文件中对HTML、CSS、javascript进行优化,那么主要就是<template>
、<style>
、<script>
中可优化的点:
- computed 和 watch 区分使用场景
- computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
- watch:类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
- v-if 和 v-show 区分使用场景
v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show则适用于需要非常频繁切换条件的场景。这里要说的优化点在于减少页面中 dom 总数,我比较倾向于使用 v-if,因为减少了 dom 数量。 - v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- v-for 遍历必须为 item 添加 key,循环调用子组件时添加 key,key 可以唯一标识一个循环个体,可以使用例如 item.id 作为 key
- 避免同时使用 v-if,v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度。
- 图片懒加载
vue-lazyload可参考下官方介绍,不再赘述。 - style方面
- style文件按照模块划分,无论放在内外都
<style lang="scss" scoped>
锁住样式,目的就是避免多人开发样式混乱,锁住之后内部的命名也可以很简短。 - 全局样式抽象化,将公共组件以及elementUI修改的样式建议都放到公共样式,抽象做的越好说明你的样式文件体积越小,复用率越高。
- style文件按照模块划分,无论放在内外都
- 合理组件化
- 使用重复率高的模块尽量封装成组件,包括布局的封装,按钮,表单,提示框,弹出框等,封装的组件只处理
类似业务,复用率越高越好 - 封装组件配置的 props 细化到一个字段,不要一个对象传进去,这样只传需要修改的参数,在子组件 props 里加数据类型,是否必传,以及默认值,便于排查错误,让传值更严谨。
- 使用重复率高的模块尽量封装成组件,包括布局的封装,按钮,表单,提示框,弹出框等,封装的组件只处理
结尾:另外还有诸如SSR(服务端渲染),首页骨架屏加载等优化方法都可以考虑下,还有其他优化点铁子们可以评论区一块讨论下~