Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。得益于 Vue 的响应式系统和虚拟 DOM 系统,性能足够的优秀,因此,Vue 应用的开发者一般不需要做额外的优化工作。但在实践中仍然有可能遇到性能问题,下面介绍一些关于 Vue 前端项目性能优化的建议。
开启路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
查看Vue路由懒加载
按需加载第三方库
现在,开发前端项目基本都避免不了要使用一些第三方库,随着项目进度,通常第三方库用的越来越多,严重影响页面性能。按需加载是针对某些第三方库体积比较大的情况下,优化webpack打包后的js体积,减少页面的加载时间。建议使用Webpack Bundle Analyzer分析器,它使用交互式可缩放树图可视化Webpack输出文件的大小。
常见第三方库按需按需引入方法如下:
使用 Vue Virtual Scroller 优化长列表
当你需要在某个页面中显示大量的行,或者需要循环大量的数据时,你可能已经注意到页面可能会很快变得非常慢。要解决这个问题,建议使用vue-virtual-scoller。它将只渲染列表中可见的项,并重用组件和 dom 元素,效率高,性能好。
避免滥用 Watch
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
详情移步计算属性 vs 侦听属性
模板预编译
当使用 DOM 内模板或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。通常情况下这个过程已经足够快了,但对性能敏感的应用还是最好避免这种用法。
预编译模板最简单的方式就是使用单文件组件——相关的构建设置会自动把预编译处理好,所以构建好的代码已经包含了编译出来的渲染函数而不是原始的模板字符串。
如果你使用 webpack,并且喜欢分离 JavaScript 和模板文件,你可以使用 vue-template-loader,它也可以在构建过程中把模板文件转换成为 JavaScript 渲染函数。
提取组件的 CSS
当使用单文件组件时,组件内的 CSS 会以 <style> 标签的方式通过 JavaScript 动态注入。这有一些小小的运行时开销,如果你使用服务端渲染,这会导致一段“无样式内容闪烁 (fouc)”。将所有组件的 CSS 提取到同一个文件可以避免这个问题,也会让 CSS 更好地进行压缩和缓存。
查阅这个构建工具各自的文档来了解更多:
- webpack + vue-loader (vue-cli 的 webpack 模板已经预先配置好)
- Browserify + vueify
- Rollup + rollup-plugin-vue
使用keep-alive缓存动态组件状态
keep-alive是vue官方提供的缓存组件。它是一个抽象组件,在页面中使用keep-alive组件缓存,能有效提高页面响应速度,组件被卸载后不会被destroy掉,而是变成不活跃状态存在内存中,当再次访问组件时直接从内存中获取缓存渲染,而不是重新请求。
资源的合并与压缩
资源的合并与压缩是web性能优化的基础手段。资源的合并与压缩主要涉及减少HTTP请求数量,减少请求资源的大小。当然,官方脚手架@vue/cli已经做这些配置。如果你是自己搭建Vue开发环境,那么你需要针对js、css、图片等资源进行合并与压缩处理。
使用CDN加速
打包时不打包 vue、vuex、vue-router、axios 等,减小打包文件。建议使用CDN加速服务,或换用国内的 bootcdn 直接引入到根目录的 index.html 中。例如:1
2
3
4<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
在 webpack 里有个 externals,可以忽略不需要打包的库:1
2
3
4
5
6externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios'
}