vuejs專案效能優化總結

Harhao發表於2019-05-18

在使用elementUI構建公司管理系統時,發現首屏載入時間長,載入的網路資源比較多,對系統的體驗性會差一點,而且用webpack打包的vuejs的vendor包會比較大。所以通過蒐集網上所有對於vuejs專案的效能優化,做了有關3方面的優化建議,主要包括:上線程式碼包打包、原始碼編寫優化、使用者體驗優化。(下面的優化建議只在vue-cli腳手架下做過測試,詳情請參考)

1.程式碼包優化

遮蔽sourceMap

待下專案開發完成。進行打包原始碼上線環節,需要對專案開發環節的開發提示資訊以及錯誤資訊進行遮蔽,一方面可以減少上線程式碼包的大小;另一方面提高系統的安全性。在vuejs專案的config目錄下有三個檔案dev.env.js(開發環境配置檔案)、prod.env.js(上線配置檔案)、index.js(通用配置檔案)。vue-cli腳手架在上線配置檔案會自動設定允許sourceMap打包,所以在上線前可以遮蔽sourceMap。如下所示,index.js的配置如下,通用配置檔案分別對開發環境和上線環境做了打包配置分類,在build物件中的配置資訊中,productionSourceMap修改成false:

'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {},

    // Various Dev Server settings
    host: 'localhost', // can be overwritten by process.env.HOST
    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-

    
    /**
     * Source Maps
     */

    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map',

    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true,

    cssSourceMap: true
  },

  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/ndindex.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',

    /**
     * Source Maps
     */

    productionSourceMap: false,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: true,
    productionGzipExtensions: ['js', 'css','svg'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}
複製程式碼

對專案程式碼中的JS/CSS/SVG(*.ico)檔案進行gzip壓縮

在vue-cli腳手架的配置資訊中,有對程式碼進行壓縮的配置項,例如index.js的通用配置,productionGzip設定為true,但是首先需要對compress-webpack-plugin支援,所以需要通過 npm install --save-dev compression-webpack-plugin(如果npm install出錯了,就使用cnpm install安裝。可能網路比較差npm install會出現頻率比較大),gzip會對js、css檔案進行壓縮處理;對於圖片進行壓縮問題,對於png,jpg,jpeg沒有壓縮效果,對於svg,ico檔案以及bmp檔案壓縮效果達到50%,在productionGzipExtensions: ['js', 'css','svg']設定需要進行壓縮的什麼格式的檔案。對專案檔案進行壓縮之後,需要瀏覽器客戶端支援gzip以及後端支援gzip。下面可以檢視成功支援gzip狀態:

'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/ndindex.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',

    /**
     * Source Maps
     */

    productionSourceMap: false,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: true,
    productionGzipExtensions: ['js', 'css','svg'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}
複製程式碼

ResponseHeader- content-encoding:

對路由元件進行懶載入

在路由配置檔案裡,這裡是router.js裡面引用元件。如果使用同步的方式載入元件,在首屏載入時會對網路資源載入載入比較多,資源比較大,載入速度比較慢。所以設定路由懶載入,按需載入會加速首屏渲染。在沒有對路由進行懶載入時,在Chrome裡devtool查閱可以看到首屏網路資源載入情況(6requests 3.8MB transfferred Finish:4.67s DOMContentLoaded 2.61s Load 2.70s)。在對路由進行懶載入之後(7requests 800kb transffered Finish2.67s DOMContentLoaded 1.72s Load 800ms),可以看見載入速度明顯加快。但是進行懶載入之後,實現按需載入,那麼專案打包不會把所有js打包進app.[hash].js裡面,優點是可以減少app.[hash].js體積,缺點就是會把其它js分開打包,造成多個js檔案,會有多次https請求。如果專案比較大,需要注意懶載入的效果。

  // 實現懶載入方式
    import Vue from "vue";
    import Router from "vue-router";
    Vue.use(Router);
    export default new Router({
    mode: "history",
    base: "/facex/district/",
    routes: [
      { path: "/", redirect: "index" },
      {
      path: "/",
      name: "home",
      component: resolve=>require(["@/views/home"],resolve),
      children: [
        {
          // 員工查詢
          path: "/employees",
          component: resolve=>require(["@/components/employees"],resolve)
        },
      {
        // 首頁
        path: "/index",
        component: resolve=>require(["@/views/index"],resolve)
      },
      {
        // 訪客查詢
        path: "/visitorlist",
        component: resolve=>require(["@/components/visitorlist"],resolve)
      },
      {
        path: "/department",
        component: resolve=>require(["@/views/department"],resolve)
      },
      //識別查詢
      {
        path: "/discriminate",
        component: resolve=>require(["@/components/discriminate"],resolve)
      },
      {
        path: "/addDevice",
        component: resolve=>require(["@/views/addDevice"],resolve)
      },
      {
        path: "/districtNotice",
        component: resolve=>require(["@/components/districtNotice"],resolve)
      }
    ]
  },
  {
    path: "/noticeList",
    name: "noticeList",
    component: resolve=>require(["@/views/noticeList"],resolve)
    },
    {
      path: "/login",
      name: "login",
      component: resolve=>require(["@/views/login"],resolve)
    },
    {
      path: "/register",
      name: "register",
      component: resolve=>require(["@/views/register"],resolve)
    },
    {
      path: "/setaccount",
      name: "setaccount",
      component:resolve=>require(["@/views/setaccount"],resolve)
    },
    {
      path: "/addGroup",
      name: "addGroup",
      component:resolve=>require(["@/views/addGroup"],resolve)
    },
    {
      path: "/guide",
      name: "guide",
      component:resolve=>require(["@/components/guide"],resolve)
    },
    {
      path: "/addNotice",
      name: "addNotice",
      component: resolve=>require(["@/views/addNotice"],resolve)
      }
    ]
  });i
複製程式碼

2.原始碼優化

v-if 和 v-show選擇呼叫

v-show和v-if的區別是:v-if是懶載入,當狀態為true時才會載入,並且為false時不會佔用佈局空間;v-show是無論狀態是true或者是false,都會進行渲染,並對佈局佔據空間對於在專案中,需要頻繁呼叫,不需要許可權的顯示隱藏,可以選擇使用v-show,可以減少系統的切換開銷。

為item設定唯一key值,

在列表資料進行遍歷渲染時,需要為每一項item設定唯一key值,方便vuejs內部機制精準找到該條列表資料。當state更新時,新的狀態值和舊的狀態值對比,較快地定位到diff。

細分vuejs元件

在專案開發過程之中,第一版本把所有的元件的佈局寫在一個元件中,當資料變更時,由於元件程式碼比較龐大,vuejs的資料驅動檢視更新比較慢,造成渲染比較慢。造成比較差的體驗效果。所以把元件細分,比如一個元件,可以把整個元件細分成輪播元件、列表元件、分頁元件等。

減少watch的資料

當元件某個資料變更後需要對應的state進行變更,就需要對另外的元件進行state進行變更。可以使用watch監聽相應的資料變更並繫結事件。當watch的資料比較小,效能消耗不明顯。當資料變大,系統會出現卡頓,所以減少watch的資料。其它不同的元件的state雙向繫結,可以採用事件中央匯流排或者vuex進行資料的變更操作。

內容類系統的圖片資源按需載入

對於內容類系統的圖片按需載入,如果出現圖片載入比較多,可以先使用v-lazy之類的懶載入庫或者繫結滑鼠的scroll事件,滾動到可視區域先再對資料進行載入顯示,減少系統載入的資料。

SSR(服務端渲染)

如果專案比較大,首屏無論怎麼做優化,都出現閃屏或者一陣黑屏的情況。可以考慮使用SSR(服務端渲染),vuejs官方文件提供next.js很好的服務端解決方案,但是侷限性就是目前僅支援Koa、express等Nodejs的後臺框架,需要webpack支援。目前自己瞭解的就是後端支援方面,vuejs的後端渲染支援php,其它的不太清楚。

3.使用者體驗優化

better-click防止iphone點選延遲

在開發移動端vuejs專案時,手指觸控時會出現300ms的延遲效果,可以採用better-click對ipone系列的相容體驗優化。

菊花loading

菊花loading,在載入資源過程之中,可以提供loading。此菊花loading不是那菊花。所以可以自由選擇自己喜歡的菊花。

太帥

骨架屏載入

在首屏載入資源較多,可能會出現白屏和閃屏的情況。體驗不好。盜圖一波,小米商城使用骨架屏進行首屏在資源資料還沒有載入完成時顯示,給很好的體驗效果。

2018052209545810.gif

參考文章:
Vue頁面骨架屏的實現方法
淺談 Vue 專案優化
Vue 初始化效能優化
Vue 效能優化經驗總結
路由懶載入
VUE2元件懶載入淺析
基於VUE的SPA單頁應用開發-載入效能篇

相關文章