vue性能优化

641 阅读12分钟

怎样做到vue项目中的性能优化:

下面主要从一下几几方面进行进行分析:

  • 代码书写习惯
  • 加载
  • 提升用户体验
  • SEO
  • 后端角度优化

一.代码书写习惯

1.不需要做响应式的数据,不要放在data中

data 不要把所有的数据都放到data中,只把你需要做响应式的数据放到data中,如果一个数据放到了data中,vue会给这个数据添加一个getter和setter,当你获取数据调用getter,当你设置数据调用setter,性能不高。

2.v-if v-show

v-show和v-if的区别是:v-if是懒加载,当状态为true时才会加载,并且为false时不会占用布局空间;v-show是无论状态是true或者是false,都会进行渲染,并对布局占据空间对于在项目中,需要频繁调用,不需要权限的显示隐藏,可以选择使用v-show,可以减少系统的切换开销。

3.v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

(1)v-for 遍历必须为 item 添加 key

在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。

注意:这个key,尽量使用id,不要用index索引做key值,就像请求到后端的那个数据中,每个值,都有唯一的一个id.

(2)v-for 遍历避免同时使用 v-if

v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。

推荐使用:

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>
computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
	 return user.isActive
    })
  }
}

不推荐使用:

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>

4.能拆分的组件尽可能拆分 颗粒度尽可能小

提高利用性,增加代码的可维护性 提高代码的复用性 减小不必要渲染

5.SPA(Single Page Application)单页应用开发

常见的几种SPA优化方式

  • 减小入口文件体积
  • 静态资源本地缓存
  • 开启GZip压缩
  • 使用SSR

1.减小入口文件体积,

常用的手段是路由懒加载,开启路由懒加载之后,待请求的页面会单独打包js文件,使得入口文件index.js变小,开启懒加载之后,js是这样请求加载的:

2.静态文件本地缓存有两种方式

  • HTTP缓存,设置Cache-Control,Last-Modified,Etag等响应头
  • Service Worker离线缓存,缺点:需要在HTTPS站点下

3.GZip压缩和使用SSR原理都比较简单,我们很容易想到这两种方式是如何提高页面加载速度的。

注意:但是除了上面几种方式,另外一种优化方案也不容小觑,这也是我在近期项目开发中使用并理解到的。我们先说说通常项目中是如何加载页面数据:Vue组件生命周期中请求异步接口,在mounted之前应该都可以,据我了解绝大部分同学是在mounted的时候执行异步请求。但是我们可以把页面需要的请求放到Vue-Router的守卫中执行,意思是在路由beforeEnter之前就可以请求待加载页面中所有组件需要的数据,此时待加载页面的Vue组件还没开始渲染,而Vue组件开始渲染的时候我们就可以用Vuex里面的数据了。

参考:www.cnblogs.com/wukong-holm…

4.keep-alive 可以实现组件的缓存,把组件中的结构和数据全部缓存到内存

vue组件keep-alive
如果你做用一个大型web的spa的时候,你有很多router,对应的是很多个页面。在页面的快速切换中,为了保证页面加载的效率,除了缓存机制之外,vue的keep-alive组件可以帮的上忙。

它会把组件保存在浏览器内存当中,方便你快速切换。

百度的lavas项目中就在vue-router当中使用keep-alive的组件,用它包裹着router-view。使用了keep-alive的组件内的数据将会保留,“是否需要重新同步数据”可以在vue-router的钩子中路由所带的参数执行判断。

6.路由的懒加载

Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。

component: Cart = () => import('./Cart.vue')

7.动态导入组件 按需导入

//不推荐:
improt xx form "xx"
components:{xx}
//推荐:
components:{ yyy:()=>import(yyy)}

8.Object.freeze 也会实现数据劫持,冻结

Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

二.加载

1.图片资源懒加载

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件:

<img v-lazy="/static/img/1.png">

2.第三方插件的按需引入

我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。以下为项目中引入 element-ui 组件库为例:

import { Button, Select } from 'element-ui';

三.提升用户体验

1.骨架屏

骨架屏可以理解为是当数据还未加载进来前,页面的一个空白版本,一个简单的关键渲染路径。可以看一下下面Facebook的骨架屏实现,可以看到在页面完全渲染完成之前,用户会看到一个样式简单,描绘了当前页面的大致框架的骨架屏页面,然后骨架屏中各个占位部分被实际资源完全替换,这个过程中用户会觉得内容正在逐渐加载即将呈现,降低了用户的焦躁情绪,使得加载过程主观上变得流畅。

这就是一个简单的骨架屏:

这个插件 vue-skeleton-webpack-plugin,它将插入骨架屏的方式由手动改为自动,原理在构建时使用 Vue 预渲染功能,将骨架屏组件的渲染结果 HTML 片段插入 HTML 页面模版的挂载点中,将样式内联到 head 标签中。这个插件可以给单页面的不同路由设置不同的骨架屏,也可以给多页面设置,同时为了开发时调试方便,会将骨架屏作为路由写入router中,

2.PWA

支持缓存HTML文档、接口(get)等,降低页面白屏时间 这样即使在弱网甚至断网情况下,也能迅速展示出页面

四.SEO

那么,到底什么是seo呢,从官方的解读来看,Search Engine Optimization(搜索引擎优化),seo也就是搜索引擎优化。

简单的说:seo是基于搜索引擎营销的一种网络营销推广方式,通过使用seo技术,提升网站关键词排名和公司产品的曝光度,获得用户点击,获得流量。 其中基于SEO比较常用的两种方案:SSR和预渲染 1、SSR 服务端渲染是指 Vue 在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的 html 片段直接返回给客户端这个过程就叫做服务端渲染。 (1)服务端渲染的优点:

  • 更好的 SEO: 因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;

  • 更快的内容到达时间(首屏加载更快): SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间; (2)服务端渲染的缺点:

  • 更多的开发条件限制: 例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;

  • 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源,因此如果你预料在高流量环境下使用,请准备相应的服务器负载,并明智地采用缓存策略。

如果你的项目的 SEO 和 首屏渲染是评价项目的关键指标,那么你的项目就需要服务端渲染来帮助你实现最佳的初始加载性能和 SEO。

预渲染: 如果你的 Vue 项目只需改善少数页面,或者是某公司的网站,其中一些数据很少改动,是一些死数据,你可以采用 预渲染,并可以将你的前端作为一个完全静态的站点,具体你可以使用prerender-spa-plugin插件就可以轻松的渲染。

五.后端角度优化

1.gzip压缩

在所有的web前端项目,静态资源基本都放在cdn上,gzip的压缩是非常必要的,它直接改变了js文件的大小,减少两到三倍。(nginx的gzip配置非常简单,在你对应的域名底下,添加下面的配置,重启服务即可)

2.缓存:服务器缓存和浏览器缓存 服务器缓存:

  • 为了提高服务器获取数据的速度,nginx缓存着静态资源是非常必要的。如果是测试服务器对html应该不设置缓存,而js等静态资源环境因为文件尾部会加上一个hash值,这可以有效实现缓存的控制。 浏览器缓存:
  • 浏览器缓存是通过html的头文件中的meta来控制。http-equiv是一个专门针对http的头文件,可以向浏览器传回一些有用的信息。与之对应的content,是各个参数的变量值。

3.HTTP请求

HTTP 1.0

在HTTP1.0中通过Pragma控制页面缓存,可以设置为Pragma或no-cache。在不让浏览器或中间缓存服务器缓存页面的情况下,通常设置的值为no-cache,不过这个值不这么保险,通常还加上Expires置为0来达到目的。Expires可以用于设定网页的到期时间。一旦网页过期,必须到服务器上重新传输获取新的页面信息。PS:内容必须使用GMT的时间格式。

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

HTTP 1.1

在HTTP1.1中通过Cache-Control控制页面缓存,可以设置为no-cache、private、no-store、max-age或must-revalidate等,默认为private。

<meta http-equiv="Cache-Control" content="no-cache">
  • public 浏览器和缓存服务器都可以缓存页面信息
  • private 对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允* 许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效
  • no-cache 浏览器和缓存服务器都不应该缓存页面信息
  • no-store 请求和响应的信息都不应该被存储在对方的磁盘系统中,不使用* 缓存
  • must-revalidate 对于客户机的每次请求,代理服务器必须想服务器验证* 缓存是否过时
  • max-age 客户机可以接收生存期不大于指定时间(以秒为单位)的响应
  • min-fresh 客户机可以接收响应时间小于当前时间加上指定时间的响应
  • Last-Modified和Etags
  • Last-Modified服务器端文件响应头,描述最后修改时间。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问时间点之后资源是否被修改过,从而区分200和304的请求状态码,304则选择浏览器缓存。

Etags不同的是,ETag是根据实体内容生成一段hash字符串,是标识资源的状态。它由服务端产生来判断文件是否有更新。

参考链接:juejin.cn/post/684490… www.jianshu.com/p/32733a356… www.cnblogs.com/afterwawa/p…