在前一部分,咱們學習了足夠強大的模式,能夠顯着提升應用程序的性能 - 按每一個路由分割代碼。雖然按路由分割代碼很是有用,可是在用戶訪問咱們的站點後,仍然有不少代碼是不須要的。在本系列的這一部分中,咱們將重點關注分離咱們的狀態管理(state management ) - Vuex模塊。
本系列文章基於對 Vue Storefront 性能優化過程的學習。經過使用下面的技術,咱們可以將初始文件的大小減小70%,並在眨眼間使其加載。html
在咱們進一步瞭解如何延遲加載 Vuex 模塊 以前,您須要注意一件重要的事情,瞭解註冊 Vuex 模塊的方法,以及它們的優缺點。前端
靜態 Vuex 模塊(Static Vuex modules) 是在 Store 初始化期間聲明註冊。 如下是顯式建立的靜態模塊的示例:vue
// store.js import { userAccountModule } from './modules/userAccount' const store = new Vuex.Store({ modules: { user: userAccountModule } })
上面的代碼將建立一個帶有靜態模塊 userAccountModule 新的 Vuex 實例。靜態模塊不能被取消註冊(也不能延遲註冊),而且在 Store 初始化後不能更改靜態模塊的結構(不是狀態(not state))。git
雖然這種限制對大多數模塊來講都不是問題,並且將全部模塊聲明在一個地方,確實有助於將全部與數據相關的內容保存在一塊兒,可是這種方法也有一些缺點。github
假設咱們的應用程序中有一個專用的 Vuex 模塊的 admin 面板。vue-router
// store.js import { userAccountModule } from './modules/userAccount' import { adminModule } from './modules/admin' const store = new Vuex.Store({ modules: { user: userAccountModule, admin: adminModule } })
你能夠想象這樣的模塊可能會很是的龐大。儘管 admin 面板可能只會被一小部分用戶使用,而且只能在特定的路由下使用(一個特殊的 /admin 路徑),但因爲這些靜態模塊都是被集中註冊的,最終這些代碼都會被打包到主文件中。vuex
咱們全部的模塊都打包在一個文件中segmentfault
這固然不是咱們想要的結果。咱們須要一種方法只在訪問 /admin 路由時才加載。您可能已經猜到靜態模塊不能知足咱們的須要。全部靜態模塊都須要在 Vuex Store 建立時進行註冊。api
這就是動態模塊能夠幫助咱們的地方!promise
動態模塊相比靜態模塊來講,能夠在 Vuex Store 建立後再進行註冊。這種簡潔的功能意味着咱們不須要在應用程序初始化時下載動態模塊,而是能夠將其打包在不一樣的代碼塊中,或者在須要時延遲加載。
首先,讓咱們看看前面的 admin 模塊用動態註冊是什麼樣子的:
// store.js import { userAccountModule } from './modules/userAccount' import { adminModule } from './modules/admin' const store = new Vuex.Store({ modules: { user: userAccountModule, } }) store.registerModule('admin', adminModule)
咱們沒有直接將 adminModule 模塊寫在 modules 屬性中,而是在 Vuex.Store 建立以後使用 registerModule 方法註冊這個模塊。
動態註冊不須要對模塊自己進行任何更改,所以能夠靜態或動態註冊任何 Vuex 模塊。
固然,在目前來看,這個動態註冊的模塊並無給咱們任何好處。
讓咱們回到咱們的問題上來,既然咱們知道了如何動態註冊 admin 模塊,咱們固然能夠嘗試將其代碼放入 /admin 路由文件中。
讓咱們暫時停下來,簡要了解一下咱們正在使用的應用程序:
// router.js import VueRouter from 'vue-router' const Home = () => import('./Home.vue') const Admin = () => import('./Admin.vue') const routes = [ { path: '/', component: Home }, { path: '/admin', component: Admin } ] export const router = new VueRouter({ routes })
在 router.js 中,咱們有兩個路由作了代碼分割,它們被延遲加載。使用咱們在上面看到的代碼,咱們的 admin 模塊仍然會打包到主文件 app.js 中,由於它在 store.js 中是靜態導入的。
讓咱們修復這個問題,並將此模塊僅給訪問 /admin 路由的用戶使用,這樣其餘人就不會下載冗餘的代碼。
爲此,咱們將在 /admin 路由對應的組件中加載 admin 模塊,而不是在 store.js 中導入並註冊它。
// store.js import { userAccountModule } from './modules/userAccount' export const store = new Vuex.Store({ modules: { user: userAccountModule, } }) // Admin.vue import adminModule from './admin.js' export default { // other component logic mounted () { // 在這裏動態註冊模塊 this.$store.registerModule('admin', adminModule) }, beforeDestroy () { // 當組件被銷燬時,取消註冊 this.$store.unregisterModule('admin') } }
讓咱們看看發生了什麼!
咱們在 /admin 路由對應的 Admin.vue 組件中導入了 admin 模塊,並在組件掛載(mounted)以後註冊到了 Store 中。一旦用戶退出 damin 面板,銷燬該組件,咱們就會取消註冊該模塊,以防止同一模塊被屢次註冊。
如今由於 admin 模塊是在 Admin.vue 導入的,而不是在 store.js 中導入的,因此它將與代碼分割的 admin.vue 打包在一個文件中!
重要提示:若是使用SSR模式,請確保在 mounted 鉤子中 註冊模塊。不然,它可能致使內存泄漏,由於beforeDestroy鉤子在服務器端不能執行。
如今咱們知道了如何使用動態註冊 Vuex 模塊,並適當的分配到特定路由的文件中。讓咱們看一下稍微複雜一點的用例。
假如說,咱們的 home.vue 上有一個客戶評價的部分,咱們但願用戶能夠對咱們的服務有積極的建議。這樣的評價部分有不少,咱們不想在用戶進入咱們的網站後當即顯示它們, 只有在用戶須要時才能顯示它們。咱們能夠添加「Show Testimonials」按鈕,點擊後才加載並顯示客戶評價的部分。
爲了存儲客戶評價數據,咱們還須要一個Vuex模塊。咱們稱它爲 testimonials 吧。該模塊將負責顯示之前添加的評價和添加的新評價。咱們不須要知道實現細節。
咱們但願只有用戶點擊按鈕才下載 testimonials 模塊,在此以前是不須要它的。讓咱們看看如何利用動態模塊註冊和動態導入來實現此功能,Testimonials.vue 是被 Home.vue 使用的一個組件。
讓咱們快速回顧一下代碼。當用戶單擊 "Show Testimonials" 按鈕時,將調用 getTestimonials() 方法,它負責調用 getTestimonialsModule() 來獲取 testimonials.js。一旦 promise 爲成功狀態(resolved)(這意味着模塊已被加載),咱們就會動態註冊它並觸發 action 獲取客戶評價。
多虧了動態導入,testmonials.js 內容被打包到一個單獨的文件中,只有在調用 gettestmonialsModule 方法時才下載該文件。
當咱們須要退出 admin 面板時,咱們在 beforeDestroy 生命週期鉤子中取消註冊已註冊過的模塊,若是咱們再次進入這個路由,就不會出現重複註冊的狀況。
儘管靜態 Vuex 模塊註冊對於大多數用例來講已經足夠了,可是在某些特定的狀況下,咱們可能須要使用動態註冊。
能代碼分割Vuex模塊是一個強大的工具。您在應用程序中處理的與數據相關的操做越多,就能夠從文件大小方面節省的越多。
在本系列的下一部分中,咱們將學習如何延遲加載各個組件,更重要的是,應該延遲加載哪些組件。
若是對你有幫助,請關注【前端技能解鎖】: