Vue.js應用性能優化:第一部分---介紹性能優化和懶加載

當「移動優先」(mobile-first)的方式逐漸成爲一種標準,而不肯定的網絡環境因素應該始終是咱們考慮的一點,所以保持讓應用程序快速加載變得愈來愈困難。在本系列文章中,我將深刻研究Vue性能優化技術,咱們在 Vue Storefront 中已經使用了這些技術,您也能夠在Vue.js應用程序中使用這些技術,使它們可以當即加載並順利運行。個人目標是使本系列成爲關於Vue應用程序性能的完整指南。javascript

  • Part 1 — Introduction to performance optimization and lazy loading.
  • Part 2 — Lazy loading routes and vendor bundle anti-pattern.
  • Part 3 — Lazy loading Vuex modules
  • Part 4 — Delivering good waiting experience and lazy loading individual components — soon
  • Part 5 — Lazy loading libs and finding smaller equivalents — soon
  • Part 6 — Performance-friendly usage of UI libraries
  • Part 7 — Making use of Service Worker cache — soon
  • Part 8 — Prefetching

Webpack 打包工做原理

本系列的大部分技巧將集中於使咱們的JS包更小。要理解這一點,首先咱們須要理解 Webpack 是如何打包(bundling)咱們全部的文件的。當打包咱們的資源時,Webpack 建立了被成爲依賴圖(dependency graph)的東西,它是一個基於入口,連接咱們全部文件的圖。假設咱們在webpack配置中指定了一個名爲 main.js 的文件做爲入口點,它將是依賴關係圖的根。如今,咱們將在此文件中導入的每一個js模塊將成爲圖中的節點,而且在此節點中導入的每一個模塊都將成爲其節點。Webpack 正是使用這個依賴關係圖來檢測輸出的包中應該包含哪些文件。輸出包只是一個包含依賴關係圖中全部模塊的 Javascript 文件(或後面的部分將看到多個)。css

咱們能夠圖解這個過程,像這樣:html

圖片描述

如今,當咱們知道打包是如何工做的,很明顯咱們的項目越多,初始的 javascript 包體積會變的越大。包太大,下載和解析的時間就會越長,用戶過很長時間才能看到有意義的東西。用戶等待的時間越長,他/她就越有可能離開咱們的網站。前端

簡而言之,更大的bundle = 更少的用戶。至少在大多數狀況下是這樣。vue

延遲加載

所以,當咱們仍然須要添加新特性和改進應用程序時,咱們如何可以減小包的大小?答案很容易-延遲加載和代碼分割。java

顧名思義,延遲加載就是延遲加載應用程序的某些部分。換句話說,只有在咱們真正須要的時候才加載它們。代碼分割就是將應用程序分割成這些延遲加載的塊。webpack

[]();

在大多數狀況下,您不須要在用戶訪問您的網站後當即從Javascript文件中得到全部代碼。即便咱們的應用程序中會有3個不一樣的路由,無論用戶最終會在哪一個路由上,他/她老是須要下載、解析和執行文件中三個路由的代碼,即使是隻須要訪問一個路由。多麼浪費時間和精力!git

延遲加載容許咱們分割包(split the bundle),並只提供所須要的部分,這樣用戶就不會浪費時間下載和解析不被使用的代碼。github

要查看咱們的網站實際使用了多少JavaScript代碼,咱們能夠到開發者工具 -> cmd+shift+p -> type coverage -> 點擊 'record'。如今咱們應該可以看到實際使用了多少下載的代碼。web

圖片描述

全部標記爲紅色的東西都是當前路由上不須要的,能夠延遲加載。若是您正在使用源碼映射(source maps ),您能夠單擊此列表中的任何文件,查看它的哪些部分沒有被調用。咱們能夠看到,即便是 vuejs.org 也有很大的改進空間。

經過延遲加載適當的組件和庫,咱們設法將 Vue Storefront 的文件大小減小了60%!

好了,咱們知道什麼是延遲加載,它很是有用。

如今來看看如何在Vue.js應用程序中使用它。

動態導入 (Dynamic imports)

咱們能夠輕鬆地用 webpack dynamic imports 加載應用程序的某些部分。讓咱們看看它們是如何工做的,以及它們與常規導入有何不一樣。

若是咱們將以這樣的標準方式導入JS模塊:

// main.js
import ModuleA from './module_a.js'
ModuleA.doStuff()

它將做爲 main.js 的一個節點添加到依賴關係圖中,並與之打包在一塊兒。

可是,若是咱們僅在某些狀況下須要 ModuleA,例如對用戶交互的響應,那該怎麼辦呢?將這個模塊與初始文件打包在一塊兒不是一個好主意,由於可能根本不須要它。咱們須要一種方法來告訴應用程序什麼時候應該下載這段代碼。

這就是動態導入能夠幫助咱們的地方!如今看看這個例子:

//main.js
const getModuleA = () => import('./module_a.js')
// 做爲對某些用戶交互的響應調用
getModuleA()
  .then({ doStuff } => doStuff())

讓咱們快速看看這裏發生了什麼:

咱們沒有直接導入 module_a.js,而是建立了一個返回 import() 函數的函數。如今webpack將動態導入模塊的內容打包到一個單獨的文件中,除非函數被調用,不然不會導入也不會下載文件。在稍後的代碼中,咱們下載了這段可選代碼,做爲對某些特定用戶交互的響應(如路由更改或單擊)。

經過動態導入,咱們基本上隔離了將添加到依賴關係圖中的給定節點(在本例中是 module_a),並在肯定須要時下載這一部分(這意味着咱們還切斷了在module_a.js中導入的模塊)。

讓咱們看另外一個例子,它將更好地說明這種機制。

假設咱們有4個文件: main.js, module_a.jsmodule_b.jsmodule_c.js。要了解動態導入的工做原理,咱們只須要 mainmodule_a 的源代碼:

//main.js
import ModuleB from './mobile_b.js'
const getModuleA = () => import('./module_a.js')
getModuleA()
  .then({ doStuff } => doStuff()
)
//module_a.js
import ModuleC from './module_c.js'

經過使 module_a 成爲一個動態導入的模塊,咱們把 module_a 及其全部的子模塊從依賴圖切割成一部分。當 module_a 被動態導入時,它與其中導入的模塊一塊兒加載。換句話說,咱們只是爲依賴關係圖建立了一個新的入口點。

圖片描述

這就是咱們的依賴關係圖和文件包在給定設置下的樣子。

延遲加載Vue組件

咱們知道什麼是延遲加載,以及爲何須要它。如今看看如何在Vue應用程序中使用它。

好消息是它很是簡單,咱們能夠延遲加載整個SFC(譯者注:Vue Single-File Component -- 單文件組件)以及它的css和html,語法與以前如出一轍!

const lazyComponent = () => import('Component.vue')

這就是你所須要的! 如今只有在請求時纔會下載組件。 如下是調用Vue組件動態加載的最經常使用方法:

  • 調用帶有導入的函數
const lazyComponent = () => import('Component.vue')
lazyComponent()
  • 組件請求後渲染
<template>
  <div> 
    <lazy-component />
  </div>
</template>
<script>
const lazyComponent = () => import('Component.vue')
export default {
  components: { lazyComponent }
}
</script>

請注意,只有當組件被請求要在模板中渲染時,纔會調用 lazyComponent 函數。
例以下面的代碼:

<lazy-component v-if="false" />

這樣不會動態導入組件,由於它並無添加到DOM中(可是當值變爲true時就會動態導入,這是一種延遲加載Vue組件的好方法)。

總結

延遲加載是提升web應用程序性能並減小其大小的最佳方法之一。咱們學習瞭如何使用Vue組件的延遲加載。在本系列的下一部分中,我將向您展現如何使用 Vue-routerasync 路由來分割Vue應用程序代碼。

若是對你有幫助,請關注【前端技能解鎖】:
qrcode_for_gh_d0af9f92df46_258.jpg

相關文章
相關標籤/搜索