這是我們的*Vue.js Performance系列中的第1部分。
雖然移動優先方法成為标準且不确定的網絡條件是我們應該始終考慮的事情,但是保持應用程式快速加載變得越來越困難。在本系列中,我将深入研究我們在Vue Storefront中使用的Vue性能優化技術,并且您可以在Vue.js應用程式中使用它們使它們立即加載并順利執行。我的目标是讓這個系列成為關于Vue應用程式性能的完整而完整的指南。
Webpack bundling如何工作?
本系列中的大多數技巧都将集中在使我們的JS包。要了解它,首先我們需要了解Webpack如何捆綁所有檔案。
捆綁我們的資源時,Webpack正在建立一個稱為依賴圖的東西(點選這裡檢視它的樣子)。它是一個基于導傳入連結接所有檔案的圖表。假設我們main.js在webpack配置中有一個被指定為入口點的檔案,它将成為我們依賴圖的根。現在,我們将在此檔案中導入的每個js子產品将成為圖中的節點,并且在這些節點中導入的每個子產品都将成為其節點。
Webpack使用此依賴關系圖來檢測它應該包含在輸出包中的檔案。輸出包隻是一個(或我們将在後面的部分中看到的多個)javascript檔案,其中包含依賴圖中的所有子產品。
該捆綁包本質上是我們整個應用程式的JavaScript。
我們可以用下圖來說明這個過程:
現在我們知道捆綁是如何工作的,很明顯我們的項目越大,初始JavaScript包就越大。
更大的捆綁包,下載下傳和解析我們的使用者所需的時間越長。使用者必須等待的時間越長,他離開我們網站的可能性就越大。事實上,根據谷歌的資料,53%的移動使用者留下的頁面加載時間超過3秒。
總而言之,更大的捆綁=更少的使用者,這可以直接轉化為潛在收入的損失。Bing就是一個很好的例子 - 延遲2秒導緻每位訪客的收入損失4.3% 。
延遲加載
那麼當我們仍然需要添加新功能并改進我們的應用程式時,我們如何切斷捆綁包大小?答案很簡單 - 延遲加載和代碼分割。
顧名思義,延遲加載是延遲加載應用程式的部件(塊)的過程。換句話說,隻有在我們真正需要的時候才加載它們。代碼分割就是将應用程式分割成這些延遲加載的塊的過程。
在大多數情況下,當使用者通路您的網站時,您不需要立即使用Javascript包中的所有代碼。
例如,我們不需要花費寶貴的資源來為首次通路我們網站的訪客加載“我的頁面”區域。或者可能存在每個頁面上不需要的模态,工具提示和其他零件群組件。
當隻需要幾個部分時,在每個頁面加載時下載下傳,解析和執行整個包的所有内容都是浪費。
延遲加載允許我們拆分捆綁包并僅提供所需的部分,這樣使用者就不會浪費時間下載下傳和解析不會使用的代碼。
要檢視我們網站中實際使用了多少JavaScript代碼,我們可以轉到devtools -> cmd + shift + p -> type coverage - >hit ‘record’.。現在我們應該能夠看到實際使用了多少下載下傳的代碼。
标記為紅色的所有内容都是目前路線上不需要的東西,可以延遲加載。如果您正在使用源映射,則可以單擊此清單中的任何檔案,并檢視未調用哪些部分。正如我們所看到的,甚至vuejs.org還有很大的改進空間。
通過延遲加載适當的元件和庫,我們設法将Vue Storefront的捆綁大小減少了60%!這可能是獲得性能提升的最簡單方法。
好的,我們知道延遲加載是什麼,它非常有用。現在是時候看看我們如何在我們自己的Vue.js應用程式中使用延遲加載。
動态導入
我們可以使用webpack動态導入輕松地加載我們應用程式的某些部分。讓我們看看它們的工作原理以及它們與正常進口的差別。
如果我們以這樣的标準方式導入JavaScript子產品:
// cat.jsconst Cat = { meow: function () { console.log("Meowwwww!") }}export default Cat// main.jsimport Cat from './cat.js'Cat.meow()
它将作為main.js依賴關系圖中的a的節點添加并與其捆綁在一起。
但是,如果我們Cat僅在某些情況下需要我們的子產品,例如對使用者互動的響應,該怎麼辦?将此子產品與我們的初始捆綁包捆綁在一起是一個壞主意,因為它始終不需要。我們需要一種方法告訴我們的應用程式什麼時候應該下載下傳這段代碼。
這是動态導入可以幫助我們的地方!現在看一下這個例子:
// main.jsconst getCat = () => import('./cat.js')// later in the code as a response to some user interaction like click or route changegetCat() .then({ meow } => meow())
我們來看看這裡發生的事情:
Cat我們建立了一個傳回import()函數的函數,而不是直接導入子產品。現在,webpack會将動态導入的子產品的内容捆綁到一個單獨的檔案中。表示動态導入子產品的函數傳回一個Promise,它将使我們在解析時通路子產品的導出成員。
然後,我們可以在需要時下載下傳此可選塊。例如,作為對某個使用者互動的響應(如路由更改或單擊)。
通過動态導入,我們基本上隔離了Cat将被添加到依賴圖中的給定節點(在這種情況下)并在我們決定需要時下載下傳該部分(這意味着我們也切斷了導入的子產品Cat.js)。
讓我們看另一個更好地說明這種機制的例子。
假設我們有一個非常小的網上商店,有4個檔案:
- main.js 作為我們的主要捆綁
- product.js 對于産品頁面中的腳本
- productGallery.js 用于産品頁面中的産品庫
- category.js 對于類别頁面中的腳本
如果不深入研究細節,讓我們看看這些檔案是如何在整個應用程式中分布的:
// category.jsconst category = { init () { ... }}export default category// product.jsimport gallery from ('./productGallery.js')const product = { init () { ... }}export default product// main.jsconst getProduct = () => import('./product.js')const getCategory = () => import('./category.js')if (route === "/product") { getProduct() .then({init} => init()) // run scripts for product page}if (route === "/category") { getCategory() .then({init} => init()) // run scripts for category page}
在上面的代碼中,根據目前路由,我們動态導入其中的一個product或category子產品,然後運作init由它們兩者導出的函數。
知道動态導入是如何工作的我們知道product并且category最終會以單獨的捆綁包結束,但是productGallery未動态導入的子產品會發生什麼?正如我們所知,通過使子產品動态導入,我們正在削減依賴圖的一部分。在此部件中導入的所有内容都将捆綁在一起,是以productGallery最終将與product子產品捆綁在一起。
換句話說,我們隻是為依賴圖建立某種新的入口點。
延遲加載Vue元件
現在我們知道延遲加載是什麼以及為什麼需要它。現在是時候看看我們如何在Vue應用程式中使用它了。
好消息是它非常簡單,我們可以懶得加載整個單一檔案元件,它的CSS和HTML使用與以前相同的文法!
const lazyComponent = () => import('Component.vue')
......這就是你所需要的!現在隻有在請求時才會下載下傳元件。以下是調用Vue元件動态加載的最常用方法:
- 調用帶導入的函數
const lazyComponent = () => import('Component.vue')lazyComponent()
- 請求元件呈現
請注意,僅當請求元件在模闆中呈現時,才會調用lazyComponent函數。例如這段代碼:
在DOM中需要元件之前,元件将不會加載,隻要v-if值更改為true即可。
總結和接下來會發生什麼
延遲加載是使您的Web應用程式更高效并減少捆綁包大小的最佳方法之一。我們學習了如何使用Vue元件進行延遲加載。
在本系列的下一部分中,我将向您展示在任何Vue.js應用程式上獲得顯着性能提升的最有用(也是最快)的方法。
您将學習如何使用異步路由拆分Vue代碼以及此過程的建議最佳實踐。
翻譯自:https://vueschool.io/articles/vuejs-tutorials/lazy-loading-and-code-splitting-in-vue-js/?source=post_page---------------------------