我的 vue 項目的優化總結

主要說的是,我在項目中,本身遇到的一些小問題和解決方案

圖片 base64 問題

// 有一個 test 的組件
<template>
  <div class='icon'></div>
</template>
<style>
  .icon {
    background: url(../assets/test.png);
  }
</style>

// 而後有三個頁面,引入了 test 組件
// h1.vue, h2.vue, h3.vue 分別都引入 test 組件
<template>
  <test></test>
</template>
<script>
import test from '@/components/test.vue'
// ...
</script>

第一次打包文件以後,三個頁面的 js 文件,都會出現相同的一個 base64 圖片css

後面第二次打包使用 import 進行引用,或者直接在標籤寫死,就不會出現上面這種狀況html

import a from 'a.jpg'
<div style='backgroundImage: url(a.jpg)'></div>

使用 keep-alive

使用 keep-alive 對某些頁面進行緩存vue

// app.vue
<keep-alive :include="['a', 'b', 'c']">
  <router-view></router-view>
</keep-alive>

router-view 父級,加上一層 keep-alive,再使用 include ,告訴 vue 有哪些頁面須要緩存,就好了。webpack

其中 a, b, c 是 .vue 文件的 name 屬性值ios

keep-alive 標籤,支持兩個屬性web

  • include: 只有匹配的組件會被緩存
  • exclude: 任何匹配的組件都不會被緩存

會被緩存的頁面(其實就是一個 vue 組件),離開時,vue 會在內部緩存當前組件的狀態,下次再次進入這個頁面,就會顯示離開時的狀態vue-router

若是有些需求,須要你在特定得狀態下,才須要緩存,而在其餘時間,進入頁面都是保持最初的狀態時,咱們可使用 vue 的一個方法,去銷燬該組件,達到刷新的效果vuex

activateddeactivated 鉤子函數事件中,使用 this.$destroy() 這個方法進行銷燬組件npm

使用 keepa-alive 的好處,緩存組件,的確是很好,我在項目體驗中,更重要是緩存頁面離開時的狀態,這個真得很是棒。axios

好比我在一個支付頁面,有 M 種狀態,而後要用戶去另一個頁面去設置密碼後,才能支付(特定需求),這時不能用一個遮罩去擋住,而是真正得跳轉另外一個頁面,而後用戶在另一個頁面操做完後,跳回去支付頁面,此時支付頁面仍是維持離開時的狀態,大大減小了不少工做(能夠用 vuex 實現此效果,不過有點麻煩)

並且配上鉤子函數和 $destroy 銷燬組件的方法,能夠處理好各類狀況

2018.01.15 更新

使用 $destroy 對組件進行銷燬,會有個 BUG。

有三個頁面 A,B,C。B 頁面是要進行緩存的。B 頁面,配置了 keep-alive

A -> B

B -> C(B 到 C 要進行緩存,因此不銷燬)

C -> B (B 維持跳去 C 時的狀態)

B -> A (不緩存)

A -> B

B -> C(B 到 C 要進行緩存,因此不銷燬)

C -> B (這時候就會出問題了!,會觸發 activated 和 created 兩個鉤子函數。在 vue 的 issue 中有人提出過這個問題,尤大也說了不支持。這裏是連接)

解決方案:

我如今是把頁面加進去 keep-alive 裏面,而後離開時,判斷下次進入要不要刷新頁面。若是要刷新頁面,手動把 state 更新…..超級麻煩,不優雅

2018.01.17 更新

有一個新的解決方案,動態的修改 include,達到更新的效果

好比,t1 組件是要緩存的

<keep-alive :include='array'>
  <router-view></router-view>
</keep-alive>
// ...
watch: {
  $route(to) {
    if (to.name === 't1') {
      this.array = 't1'
    }
  }
}

每次要去到 t1 頁面,對頁面設置爲緩存。而後在 t1 頁面要跳去其餘頁面時候,判斷是否須要緩存頁面,若是不須要,修改 array 這個值。而這個 array 值,應該存在 vuex 中,這樣能夠更好地處理它

代碼分割

router.js 文件裏

{ path: '/home', component: resolve => require(['@/module/home'], resolve) },
{ path: '/h1', component: resolve => require(['@/module/h1'], resolve) },
{ path: '/h2', component: resolve => require(['@/module/h2'], resolve) }

這裏使用了 vue-router 的懶加載,結合 webpack 的代碼分割,將代碼按頁面進行分割,達到懶加載效果。進入某個頁面,會按需加載 js 文件,有效地下降首屏文件大小

但這裏有個問題,若是某頁面的 js 文件很大,用戶在跳轉頁面時,會出現暫時性的白屏或者沒法點擊的狀況,影響用戶體驗

這裏我以爲就要根據項目狀況去考慮了。在某個項目中,有5個頁面是沒用代碼分割的,而這5個頁面,瀏覽數會比較多,而且文件的大小相對會比較大。因此取消使用了代碼分隔後,當用戶首次點入這幾個頁面,就不會出現延遲的狀況

當你這個頁面使用了不少 icon ,通過 base64 轉換後,這個 js 文件也會相對很大,是否不該該在頁面的 js 文件出現 base64 ?提早把 base64 的圖片加載了?

上面的操做都是爲了提升用戶的體驗,這個要看狀況而定了

使用代碼分割,文件的大小,會稍微比不用的時候大一點

優化依賴文件

當咱們 npm run build 後,一般能夠看到一個依賴文件,有好幾百 KB,甚至 一、2MB 大,而這個文件是全部依賴文件的集合,像 vue.js, vue-router.js, axios.js, mint-ui.js

這裏咱們可使用 webpack 的 externals 進行優化,webpack 文檔是這樣說 externals: "防止將某些 import 的包(package)打包到 bundle 中,而是在運行時(runtime)再去從外部獲取這些擴展依賴"

externals 其實不少大神的優化貼都有寫了,根據本身得體驗,這裏只是簡單得說明

咱們在 index.html 引入兩個 js

<script src="//cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
<script src='//cdn.bootcss.com/mint-ui/2.2.3/index.js'></script>

webpack.base.conf.js 裏,添加一代代碼

externals: {
  'vue': 'Vue',
  'mint-ui': 'MINT'
}

這樣就能無縫切換,使用 cdn 去加載比較大的依賴文件,減小打包後的 bundle 文件大小

打包文件大小對比

沒有使用 externals 的狀況, vendor.js 文件是 307KB

使用 externals 的狀況, vendor.js 文件是 107KB

這裏面是去掉了 vue 和 mint-ui 兩個 js 文件,而這兩個 js 文件經過外鏈 cdn 進行引用,兩個 js 文件大約都是 31KB 左右,這裏面節省了 140KB 左右的大小

這樣作,雖然加多了 HTTP 請求,可是不會影響併發的數量,並且大大減小了單個文件的大小,性能更好

在 ngrok 裏運行時,會運行得更快(測試過)

使用 v-once

在 vue 文檔中,是這樣提示的:對低開銷的靜態組件使用 v-once

使用了 v-once ,除了第一次的渲染,後面就不會再次渲染了

<div v-once>{{ a }}</div>

<script>
// ...
data() {
  return {
    a: 1
  }
},
created() {
  this.a = 2
}
</script>

最後 div 仍是顯示 1。這能夠用於優化更新性能

總結

以上的一些問題,在 PC 端好像影響不大,移動端的話,仍是比較嚴重的。不少優化點都是根據實際狀況入手,上面這幾個,都是我在作項目時,感受不合適而進行優化的,後面會持續補充下去~

相關文章
相關標籤/搜索