从4个方面优化你的Vue项目

首发于GitHib:github.com/SimonZhangI…javascript

运行时优化

一、使用v-if代替v-show

二者的区别是:v-if不渲染DOM,v-show会预渲染DOMcss

除如下状况使用v-show,其余状况尽可能使用v-ifhtml

  • 有预渲染需求vue

  • 须要频繁切换显示状态java

二、v-for必须加上key,并避免同时使用v-if

通常咱们在两种常见的状况下会倾向于这样作:webpack

  • 为了过滤一个列表中的项目 好比 v-for="user in users" v-if="user.isActive"。在这种情形下,请将 users替换为一个计算属性 (好比activeUsers),让其返回过滤后的列表git

  • 为了不渲染本应该被隐藏的列表 好比 v-for="user in users" v-if="shouldShowUsers"。这种情形下,请将 v-if 移动至容器元素上 (好比 ul, ol)github

三、事件及时销毁

Vue组件销毁时,会自动清理它与其它实例的链接,解绑它的所有指令及事件监听器,可是仅限于组件自己的事件。web

也就是说,在js内使用addEventListener等方式是不会自动销毁的,咱们须要在组件销毁时手动移除这些事件的监听,以避免形成内存泄露,如:vue-router

created() {
  addEventListener('touchmove', this.touchmove, false)
},
beforeDestroy() {
  removeEventListener('touchmove', this.touchmove, false)
}
复制代码

首屏优化

一、图片裁剪、使用webp

  • 图片须要裁剪,通常使用二倍图便可

  • 尽可能使用webp图片

  • 若是使用了vue-lazyload插件,可使用如下方法一键替换webp(替换使用v-lazy指令的图片)

Vue.use(VueLazyload, {
  error: require('./assets/img/defaultpic_small.png'),
  filter: {
    webp (listener: any, options: any) {
      if (!options.supportWebp) return
      // listener.src += '.webp'
    }
  }
});
复制代码

二、资源提早请求

经测试,Vue项目中各文件的加载顺序为:router.js、main.js、App.vue、[page].vue、[component].vue,如图:

image

其中,router的加载时间相比于page.vue快近100ms,若是page.vue的文件较多,时间差别会更大 因此,能够在页面挂载、渲染的同时去请求接口数据,如在router.js中请求数据:

import Router from 'vue-router'
import store from './store'

store.dispatch('initAjax')
复制代码

三、异步路由

使用异步路由能够根据URL自动加载所需页面的资源,而且不会形成页面阻塞,较适用于移动端页面

建议主页面直接import,非主页面使用异步路由

使用方式:

{
  path: '/order',
  component: () => import('./views/order.vue')
}
复制代码

四、异步组件

不须要首屏加载的组件都使用异步组件的方式来加载(如多tab),包括须要触发条件的动做也使用异步组件(如弹窗) 使用方式为:v-if来控制显示时机,引入组件的Promise便可

<template>
  <div>
    <HellowWorld v-if="showHello" />
  </div>
</template>
<script>
export default {
  components: { HellowWorld: () => import('../components/HelloWorld.vue') },
  data() {
    return {
      showHello: false
    }
  },
  methods: {
    initAsync() {
      addEventListener('scroll', (e) => {
        if (scrollY > 100) {
          this.showHello = true
        }
      })
    }
  }
}
</script>
复制代码

五、使用轻量级插件、异步插件

  • 使用webpack-bundle-analyzer查看项目全部包的体积大小,较大的插件包尽可能寻找轻量级的替代方案

  • 首屏用不到的插件、或只在特定场景才会用到的插件使用异步加载(如定位插件,部分状况能够经过URL传递经纬度;或生成画报插件,须要在点击时触发);插件第一次加载后缓存在本地,使用方式为:

// 以定位插件为例
const latitude = getUrlParam('latitude')
const longitude = getUrlParam('longitude')
// 若是没有经纬度参数,则使用定位插件来获取经纬度
if (!latitude || !longitude) {
  // 首次加载定位插件
  // webpack4写法,若使用webpack3及如下,则await import('locationPlugin')便可
  if (!this.WhereAmI) this.WhereAmI = (await import('locationPlugin')).default
  // do sth...
}
复制代码

六、公用CDN

使用公用的CDN资源,能够起到缓存做用,并减小打包体积

网络优化

一、减小网络请求

浏览器对同一时间针对同一域名下的请求有必定数量限制(通常是6个),超过限制数目的请求会被阻塞

首屏尽量减小同域名的请求,包括接口和js;按需减小首屏的chunk.js,合并接口请求

二、合理使用preload、dns-prefetch、prefetch

  • preload具备较高的加载优先级,它能够利用间隙时间预加载资源,将加载和执行分离开,不阻塞渲染和document的onload事件

  • 每次与域名链接都须要进行DNS解析,使用dns-prefetch能够预解析域名的DNS

  • prefetch会预加载页面未来可能用到的一些资源,优先级较低;对首屏渲染要求较高的项目不建议使用

三者的使用方式,在head标签中添加(vue-cli-3已经作了相应配置):

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <link rel="icon" href="/dist/favicon.ico" />
  <!-- dns-prefetch写法 -->
  <link rel="dns-prefetch" href="//www.dpfile.com" />
  <title>md-config</title>
  <!-- preload写法,as属性必须 -->
  <link href="/dist/css/app.52dd885e.css" rel="preload" as="style" />
  <link href="/dist/js/app.05faf3b5.js" rel="preload" as="script" />
  <link href="/dist/js/chunk-vendors.04343b1f.js" rel="preload" as="script" />
  <!-- prefetch写法 -->
  <link href="/dist/js/chunk-vendors.04343b1f.js" rel="prefetch" />
</head>
复制代码

三、PWA

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

编译打包优化

一、升级Vue-Cli-3

vue-cli-3采用webpack4+babel7,对编译打包方面作了不少优化(成倍的提高),使用yarn做为包管理工具,而且对不少优化的最佳实践作了默认配置

经测试,将项目从vue-cli-2迁移到vue-cli-3以后,速度变化为:

编译时间:44s --> 7s 打包时间:55s --> 11s

效率提高很是明显

二、SSR

对加载性能要求较高的项目建议升级SSR

相关文章
相关标签/搜索