本文主要针对自己最近项目中遇到的一些问题,并参照网上的一些文章,整理了部分 Vue 性能优化上的点。
代码优化
v-show 和 v-if 的使用
使用了v-if
的时候,如果值为false,那么页面将不会有这个 html 标签生成,而v-show
则不管值为 true 还是 false,html 元素都会存在,只是 CSS 中的 display 显示或隐藏, 因此需要频繁切换的用 v-show。
Object.freeze()
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改,冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。而在 vue 中,对于 data 或 vuex 里使用 freeze 冻结了的对象,vue 不会做 getter 和 setter 的转换,因此如果你有一个巨大的数组或者 Object,并且确信数据不会修改,使用 Object.freeze() 可以让性能大幅提升。
谨慎使用 deep watch
根据本人血与泪的教训,当你对一个巨大的 Object 或者数组使用 deep watch 时,性能的开销是你无法想象的痛。
watch, computed, update 或 beforeUpdate 中避免复杂的逻辑
复杂的逻辑可能会触发额外的组件渲染,甚至可能会引起循环渲染的问题。常见的一些情况如下:
- 在计算属性中去设置数据。
- beforeUpdate 中去设置数据,可能会让组件重新渲染。
- watch 中去修改一些值,一不小心可能会重新触发 watch。
打包优化
分析包大小
我们可以通过 webpack-bundle-analyzer 来分析我们打包后文件的组成及大小。
- 安装
npm install webpack-bundle-analyzer --save-dev
- 使用
- 配置
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
configureWebpack: {
...,
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'disabled',
generateStatsFile: true,
statsOptions: { source: false }
})
]
}
package.json
中添加脚本
"bundle-report": "webpack-bundle-analyzer --port 8888 dist/stats.json"
- 打包后执行
npm run bundle-report
浏览器会自动打开分析页面:http://127.0.0.1:8888
谨慎使用第三方库
从上面的分析图中不难发现,我的项目中引用的第三方库占用了极大的比例,而其中 codemirror, lodash, moment, element-ui 等库都是比较常见的库。但是针对这些库,我们并没有使用他们全部的组件或功能,我们使用的也许仅仅是其中的部分甚至可能只是很小的一个方法,比如我的代码中,其实只使用了 lodash 的 cloneDeep 方法。
针对以上情况,我们可以采取以下措施:
- 删除完整的 lodash,自己实现 cloneDeep 方法
- 用轻量级的 vueCodeMirrorLite 替代 codemirror
- 使用插件摆脱 moment 自带的语言环境
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
或者用轻量级的 date-fns 代替。
- 自己实现项目的组件库,摆脱 element 的依赖。
这里,推荐 Bundle Phobia 来查看引用库的大小。
路由懒加载
这个在官网中也有描述,这里就不再展开了。
总结
以上是个人的一点总结和想法,当然这也仅仅是 vue 性能优化中的冰上一角,还有很多网络,图像,缓存等等 web 实践相关的优化值得我们去思考。