上一篇文章中挂签,我們了解了代碼拆分是什么,它如何與Webpack一起工作以及如何在Vue應(yīng)用程序中使用延遲加載來使用它『⒗蓿現(xiàn)在我們將深入研究代碼祭玉,并學(xué)習(xí)最有用的代碼分割Vue.js應(yīng)用程序模式。
本系列基于Vue Storefront性能優(yōu)化過程的學(xué)習(xí)吭狡。通過使用以下技術(shù)尖殃,我們能夠?qū)⒊跏际拇笮p少70%并使其在眨眼間加載。
應(yīng)用程序增長的問題
Vue-router是一個(gè)庫划煮,允許自然地將我們的Web應(yīng)用程序拆分為單獨(dú)的頁面。每個(gè)頁面都是與某個(gè)特定URL路徑關(guān)聯(lián)的路由缔俄。
知道這一點(diǎn)弛秋,我們有一個(gè)簡(jiǎn)單的組合應(yīng)用程序,具有以下結(jié)構(gòu):
整個(gè)JS代碼捆綁在一個(gè)文件中 - app.js
您可能已經(jīng)注意到俐载,根據(jù)我們?cè)L問的路線蟹略,我們可能不需要Home.vue
或About.vue
(它依賴的lodash
)但它們都在同一個(gè)app.js
捆綁包中,無論用戶訪問什么路由都會(huì)下載遏佣。浪費(fèi)下載和解析時(shí)間挖炬!
如果我們正在下載一條額外的路線,這并不是什么大問題状婶,但你可以想象這個(gè)應(yīng)用程序越來越大意敛,任何新的添加都意味著在首次訪問時(shí)下載更大的捆綁包。
只有1秒足以讓用戶進(jìn)行心理上下文切換并且(可能)離開我們的網(wǎng)站時(shí)膛虫,這是不可接受的草姻!
Ilya Grigorik關(guān)于滑動(dòng)性能和人類感知的驚人談話https://www.youtube.com/watch?v=7ubJzEi3HuA
使用vue-router進(jìn)行基于路由的代碼分割
為了避免通過實(shí)際使其更好地使我們的應(yīng)用程序變得更糟,我們只需要使用我們?cè)谇耙黄恼轮袑W(xué)習(xí)的動(dòng)態(tài)導(dǎo)入語法為每個(gè)路由創(chuàng)建單獨(dú)的包稍刀。
像Vue.js中的其他所有東西一樣 - 它非常簡(jiǎn)單撩独。我們只需要在那里傳遞動(dòng)態(tài)導(dǎo)入功能,而不是將組件直接導(dǎo)入到路徑對(duì)象中。僅當(dāng)解析給定路線時(shí)才會(huì)下載路線組件综膀。
所以不要像這樣靜態(tài)導(dǎo)入路徑組件:
import RouteComponent form './RouteComponent.vue'
const routes = [{ path: /foo', component: RouteComponent }]
我們需要?jiǎng)討B(tài)導(dǎo)入它澳迫,這將創(chuàng)建一個(gè)包含此路由的新捆綁包作為入口點(diǎn):
const routes = [
{ path: /foo', component: () => import('./RouteComponent.vue') }
]
知道了這一點(diǎn),讓我們看看我們的捆綁和路由如何與動(dòng)態(tài)導(dǎo)入一樣:
通過此設(shè)置剧劝,webpack將創(chuàng)建三個(gè)包:
-
app.js
- 我們的主要捆綁包含應(yīng)用程序入口點(diǎn)(main.js
)和每個(gè)路徑所需的庫/組件 -
home.js
- 捆綁主頁纲刀,只有在/
輸入路徑時(shí)才會(huì)下載 -
about.js
- 捆綁大約頁面(并且它是dependendy - lodash),只有在/about
輸入路徑時(shí)才會(huì)下載担平。
*為了便于理解示绊,捆綁名稱不是webpack生成的真實(shí)名稱。
0.js
1.js
根據(jù)你的webpack配置暂论,Webapck實(shí)際上正在生成類似的東西面褐。
這種技術(shù)幾乎適用于所有應(yīng)用,并且可以提供非常好的結(jié)果取胎。
在許多情況下展哭,基于路由的代碼拆分將解決您的所有性能問題,并且可以在幾分鐘內(nèi)應(yīng)用于幾乎任何應(yīng)用程序闻蛀!
Vue生態(tài)系統(tǒng)中的代碼拆分
您可能正在使用Nuxt或vue-cli來創(chuàng)建您的應(yīng)用程序匪傍。如果是這樣,重要的是要知道它們都有關(guān)于代碼拆分的一些自定義行為:
- 在vue-cli 3中觉痛,默認(rèn)情況下將預(yù)取所有延遲加載的塊役衡。我們將在稍后學(xué)習(xí)如何使用預(yù)取。如果你想了解更多關(guān)于vue-cli中的preftching的信息薪棒,請(qǐng)參閱此主題
- 在 Nuxt中手蝎,如果我們使用Nuxt路由系統(tǒng),所有頁面路由都是開箱即用的
現(xiàn)在讓我們來看看非常流行且常用的反模式俐芯,它可以使基于路由的代碼拆分影響力降低棵介。
vendor bundle反模式
vendor包通常用于包含所有模塊的單獨(dú)js文件的上下文中node_modules
。
雖然將所有內(nèi)容放在這里以將所有依賴項(xiàng)保存在一個(gè)地方并緩存它們可能很誘人吧史,但這種方法引入了將所有路由捆綁在一起時(shí)遇到的相同問題:
你看到了問題嗎邮辽?即使我們只需要在一個(gè)路由中將lodash(它是其中一個(gè)依賴項(xiàng))vendor.js
與所有其他依賴項(xiàng)捆綁在一起,因此它將始終下載贸营。
將所有依賴項(xiàng)捆綁在一個(gè)文件中聽起來很誘人吨述,但會(huì)使您的應(yīng)用加載時(shí)間更長。我們可以做得更好莽使!
離開我們的應(yīng)用程序就像基于路由的代碼吐出一樣锐极,足以確保只下載所需的代碼。但它會(huì)導(dǎo)致一些代碼重復(fù)芳肌。
我們假設(shè)Home.vue
還需要lodash灵再。
在這種情況下肋层,從/about
(About.vue
)到/
(Home.vue
)的導(dǎo)航將最終導(dǎo)致兩次下載lodash。
它仍然比下載大量的冗余代碼更好翎迁,但是如果我們已經(jīng)有了這種依賴栋猖,那么重用它就沒有意義了,對(duì)吧汪榔?
這是webpack splitChunksPlugin
可以幫助我們的地方蒲拉。只需將這幾行添加到webpack配置中,我們就會(huì)將公共依賴項(xiàng)分組到一個(gè)單獨(dú)的包中痴腌,以便共享它們雌团。
// webpack.config.js
optimization: {
splitChunks: {
chunks: 'all'
}
}
在chunks
屬性中,我們只是告訴webpack應(yīng)該優(yōu)化哪些代碼塊士聪。將此屬性設(shè)置all
為您可能已經(jīng)猜到的意味著它應(yīng)該優(yōu)化所有這些屬性锦援。
您可以在webpack文檔中閱讀有關(guān)此過程的更多信息
總結(jié)
按路由拆分代碼是保持最初下載的捆綁包大小較低的最佳(也是最簡(jiǎn)單)方法之一。在下一部分中剥悟,我們將了解所有其他小部件(Vuex存儲(chǔ)和單個(gè)組件)灵寺,這些部件可以從主捆綁中切斷并且懶洋洋地加載。