在本篇文章中,博主总结了一些常见的vue2框架性能优化方法和项目启动出现白屏的原因,还望走过路过的同行和大神们点赞关注,多多指教,用你们发财的小手给予博主大大的鼓励👍👍👍。
vue2x 性能优化
👉1.路由懒加载,有效拆分应用大小,访问时才异步加载
- vue是单页面应用,可能会有很多的路由引入,这样使用webpack打包后的文件会很大
- 当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验
- 如果我们能把不同的路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更高效了。这样会大大提高首屏显示的速度,但是可能其他页面的速度就会降下来
const Foo=()=>import('./foo.vue')
const router=new VueRouter({
routes:[
{path:'/foo',component:Foo}
]
})
👉2. keep-alive 缓存页面,
避免重复创建组件实列,且能保留缓存组件状态。
👉3. v-for和v-if避免同时使用
- v-for遍历必须为item添加key
在列表数据进行遍历渲染时,需要为每一项item设置唯一的key值,方便vue.js内部精准找到该条列表数据。当state更新时,新的状态值和旧的状态值相比,较快的定位到diff
- v-for遍历避免同时使用v-if
v-for比v-if优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必须情况下应该替换为computed属性。
👉4. 长列表性能优化,可采用虚拟列表
vue会通过Object.defineProperty对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们不需要vue来劫持我们的数据,在大量数据展示的情况下这能够很明显的减少组件初始化的时间,那如何禁止vue劫持我们的数据呢?可以通过Object.freeze方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了
export default{
data(){
return{
users:{}
}
},
async created(){
const users=await axios.get("/api/users");
this.users=Object.freeze(users)
}
}
👉5. v-once
不再变化的数据可以使用v-once
👉6. 事件销毁,组件销毁后把全局变量和定时器销毁
Vue组件销毁时,会自动清理他与其他实例的连接,解绑它的全部指令以及事件监听器,但是仅限于组件本身的事件,如果在js内使用addEventListener等方式时不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄漏
created(){
addEventListener('click',this.click,false)
}
beforeDestory(){
removeEventListener('click',this.click,false)
}
👉7. 图片懒加载
对于图片加载过多的页面,过了提高页面的加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载,等到滚动到可视区域后再去加载,这样对于页面的加载性能上会有很大的提升,也提高了用户体验,我们在项目中使用vue-lazyload插件
1.安装
npm install vue-lazyload --save -dev
2.在入口文件main.js引入并使用
import VuelazyLoad from 'vue-lazy-load'
然后在vue中直接使用
Vue.use(VueLazyLoad)
或者添加自定义选项
Vue.use(VueLazyLoad,{
preload:1.3,
error:'dist/error.png',
loading:'dist/loading.gif',
attempt:1
})
3.在vue文件中将img标签的src属性直接改为v-lazy,从而将图片显示方式更改为懒加载显示
<img v-lazy="/static/img/1.png">
8. 第三方插件按需引入
我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的整个体积太大,我们可以借助babel-plugin-component,然后只引入需要的组件,以达到减小项目体积的目的,以下为项目中引入elementui组件库
- 首先,安装babel-plugin-component
npm install babel-plugin-component -D
- 然后将.babelrc修改为
{
"presets":[["es2015",{"modules":false}]] ,
"plugins":[
[
"component",
{
"libraryName":"element-ui",
"styleLibraryName":"theme-chalk"
}
]
]
}
- 在main.js中引入部分组件
import Vue from 'vue'
import {Button,Select} from 'element-ui'
Vue.use(Button)
Vue.use(Select)
👉9. 服务器渲染SSR or 预渲染
服务器渲染是指Vue在客户端将标签渲染成的整个html片段的工作在服务端完成,服务端形成的html片段直接返回给客户端的这个过程就叫做服务器渲染
- 服务器渲染的优点
更好的SEO: 因为SPA的内容是通过Ajax获取,而搜索引擎爬取工具并不会等待Ajax异步完成后再抓取页面内容,所以在SPA中是抓取不到页面痛过Ajax获取到的内容,而SSR是直接由服务端返回已经渲染好的页面(数据已经含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面。
更快的内容到达时间(首屏加载更快): SPA会等待所有的Vue编译后的js文件都下载完成后,才进行页面的渲染,文件下载等需要一定的时间等,所以首屏的渲染需要一定的时间;SSR直接由服务器端渲染好的页面直接返回显示,无需等待下载js文件以及再求渲染等,所以SSR有更快的内容到达时间。 - 服务器渲染的缺点
更多的开发条件限制: 例如服务器渲染只支持beforeCreate和created两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务器渲染应用程序中运行,并且可以部署在任何静态文件服务器上的完全静态单页面应用程序SPA不同,服务器渲染应用程序,需要处于Node.js server运行环境
更多的服务器负载: 在Node.js中渲染完整的应用程序,显然要比仅仅提供静态文件的server更加占用cpu资源,因此,如果你料想在高流量环境下使用,请准备响应的服务器负载,并明智的采用缓存策略。
👉10. v-if和v-show区别使用场景
- v-if 是真正的条件下渲染,因为他会确保在切换过程中条件块内的事件监听器和子组件适当地销毁和重建;也是惰性的,如果初始渲染时条件为假,则什么也不做—一直到条件第一次变为真时,才会开始渲染条件块。
- v-show 元素总是被渲染,并且只是基于css的的display属性进行切换
- 所以 v-if适用于在运行时很少改变条件,不需要频繁切换条件的场景,v-show则适用于需要非常频繁切换条件的场景。
👉11. computed和watch区分场景
- computed 是计算属性,依赖于其他的属性值,并且computed值有缓存,只要它依赖的值发生改变,下一次computed才会重新计算computed的值。
- watch 更多的时观察的作用,类似于某些值得监听回调,每当监听得数据变化时都会执行回调进行后续得操作。
- 运用场景
- 当我们需要进行数值计算,并且依赖于其他数据得时候,应该使用computed,因为可以利用computed得缓存特性,避免每次取值时,都重新计算。
- 当我们需要在数据变化时执行异步或开销较大得操作时,应该使用watch,使用watch选项允许我们执行异步操作(访问一个API),限制我们执行该操作得频率,并且我们得到最终得结果前,没有中间状态,这些都是计算属性无法做到的。
👉12. 优化无限列表性能
如果你的应用存在非常长或者无效滚动的列表,那么需要采用窗口化的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建dom节点的时间,可以参考开源项目"vue-virtual-scroll-list"和vue-virtual-scroller来优化这种无限列表的场景。
👉13. 全局事件,自定义事件要在组件销毁时解除绑定
- 内存泄露风险
- 全局事件(如 window.resize)不解除,则会继续监听,而且组件再次创建时会重复绑定
👉14. vue2.x中,无法监听data属性的新增和删除,以及数组的部分修改—vue3不会有这个问题
- vue2新增data属性,使用Vue.SET
- vue2删除data属性,使用Vue.delete
- 修改某一元素,不能arr[index]=value,要使用arr.splice API的方式
👉15. 路由切换时,页面会scroll到顶部,例如,例如在一个新闻列表下滑动到一个位置,点击进入详情,再返回列表页,此时会scroll到顶部,并重新渲染列表页,所有的spa都会有这个问题,并不仅仅是vue
- 在列表页缓存数据和scrollTop
- 返回列表时(用Vue-router导航守卫,判断from),使用缓存的数据渲染页面,然后scrollTo(scrollTop)
常见白屏原因优化
👉vue项目在开发过程中出现白屏的情况总结
- 检查浏览器控制台的报错信息。白屏通常是由Javascript报错导致的,检查浏览器控制台的报错信息,查找错误的原因。
- 检查路由配置。如果项目使用了VueRouter,可能是路由配置的问题导致了白屏,可以检查路由配置是否正确
- 检查组件的引入和使用方式。如果组件的引入和使用方式有误,也可能导致白屏,可以检查组件的引入和使用方式是否正确。
- 检查项目的依赖包是否安装完整。有时候项目依赖的包没有安装完整,也可能会导致白屏,可以检查项目的依赖包是否完整。
- 检查项目的代码是否被修改过。如果项目代码被修改过,也可能会导致白屏,可以通过版本控制工具恢复到之前的版本,查看问题是否解决。
- 检查网络连接是否正常。如果网络连接不正常,可能导致项目无法加载,也会出现白屏,可以检查网络连接是否正常。
- 检查项目的入口文件。如果项目的入口文件有误,也可能导致白屏,可以检查项目的入口文件是否正确。
- 检查项目的配置文件。如果项目的配置文件有误,也可能导致白屏,可以检查项目的配置文件是否正确。
- 检查浏览器缓存。如果浏览器缓存导致了项目加载失败,也可能会出现白屏,可以清除浏览器缓存,尝试重新加载项目。
- 检查服务器是否正常。如果服务器不正常,可能会导致项目无法正常加载,也会出现白屏,可以检查服务器是否正常运行。
- 检查开发环境是否正确。如果开发环境有误,也可能导致白屏,可以检查开发环境是否正确配置。
👉如何在开发环境中解决出现的白屏问题
- 使用 Vue Devtools 调试工具。Vue Devtools 是一款基于浏览器的 Vue.js 应用程序调试工具,它可以帮助开发者调试 Vue.js 应用程序的各个方面,包括组件层次结构、状态管理、事件监听、性能分析等。通过使用 Vue Devtools,可以更方便地排查和修复白屏问题。
- 使用 Chrome 开发者工具。Chrome 开发者工具是一款强大的 Web 开发工具,它可以帮助开发者分析和调试 Web 应用程序的各个方面,包括 HTML、CSS、JavaScript、网络请求等。通过使用 Chrome 开发者工具,可以更深入地排查和修复白屏问题。
- 使用 Vue CLI 创建新项目。如果白屏问题无法解决,可以尝试使用 Vue CLI 创建一个新的项目,将原项目中的代码逐一迁移过来,查看是否能够解决问题。
👉vue项目在开生产程中出现白屏原因及解决方法
-
路由模式有误
由于把路由模式mode设置成history。默认是hash
解决方法:
改为hash或者直接删除模式配置,如果非要用的话,在服务端加一个覆盖所有情况的候选资源 -
dist中文件引用路径错误
打包后的dist目录下的文件引用路径不对,因找不到文件而报错导致白屏
解决方法:
修改config下面index.js的模块导出路径 -
浏览器不支持es6
在项目中使用了es6语法,一些浏览器不支持es6,造成编译错误不能解析而造成白屏
解决方法:
安装Babel ,Babel 会把这些新语法转译成较低版本的代码。 -
加载文件资源过大
单页面应用的html是靠js生成,因为首屏需要加载很大的js文件(app.js和vendor.js),所以当网速差的时候会产生一定程度的白屏
路由懒加载,
//1. vue异步组件技术
{
path:"/home",
name:'Home',
component:resolve=>require(['../views/home.vue'],resolve)
}
//2. es6提案的import()
{
path:'/',
name:'home',
component:()=>import('../views/home.vue')
}
//3. webpack提供的require.ensure()
{
path:'/home',
name:'Home',
component:r=>require.ensure([],()=>r(require('../views/home.vue')),'home')
}
组件懒加载
//import方式
components:{
"dailyModal":()=>import("./dailyModal.vue")
}
// require 方式
components:{
"dailyModal":resolve=>require(['./dailyModal.vue'],resolve)
},
- CDN资源优化
CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。
随着项目越做越大,依赖的第三方 npm 包越来越多,构建之后的文件也会越来越大。再加上又是单页应用,这就会导致在网速较慢或者服务器带宽有限的情况出现长时间的白屏。此时我们可以使用 CDN 的方法,优化网络加载速度。
解决方案
1.将 vue、vue-router、vuex、axios 这些 vue 全家桶的资源,全部改为通过 CDN 链接获取,在 index.html 里插入相应链接
<body>
<div id="app"></div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.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/element-ui/2.6.1/index.js"></script>
</body>
2.在 vue.config.js 配置 externals 属性
module.exports = {
···
externals: {
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'axios':'axios'
}
}
3.卸载相关依赖的 npm 包
npm uninstall vue vue-router vuex axios
- gZip 加速优化
解决方案
所有现代浏览器都支持 gzip 压缩,启用 gzip 压缩可大幅缩减传输资源大小,从而缩短资源下载时间,减少首次白屏时间,提升用户体验。
gzip 对基于文本格式文件的压缩效果最好(如:CSS、JavaScript 和 HTML),在压缩较大文件时往往可实现高达 70-90% 的压缩率,对已经压缩过的资源(如:图片)进行 gzip 压缩处理,效果很不好。
const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
config.plugins.push(
new CompressionPlugin({
// gzip压缩配置
test: /\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 对超过10kb的数据进行压缩
deleteOriginalAssets: false, // 是否删除原文件
})
)
}
}
- vue.config.js中关闭productionSourceMap
productionSourceMap是用来报错时定位到代码位置。
如果不想让别人看到源码可以设置为false,并且可以减少打包后包的体积,加密源码。
productionSourceMap: false,
-
SSR,服务端渲染,在服务端事先拼装好首页所需的 html
-
首页加 loading或 骨架屏(优化体验)
随着 SPA 在前端界的逐渐流行,单页面应用不可避免地给首页加载带来压力,此时良好的首页用户体验至关重要。很多 APP 采用了“骨架屏”的方式去展示未加载内容,给予了用户焕然一新的体验。
所谓的骨架屏,就是在页面内容未加载完成的时候,先使用一些图形进行占位,待内容加载完成之后再把它替换掉。在这个过程中用户会感知到内容正在逐渐加载并即将呈现,降低了“白屏”的不良体验。