從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

相關文章
相關標籤/搜索