用webpack來打包你的單頁應用的一個可能的缺點是你可能會獲得一個很是大的打包文件,有時甚至會有幾兆大小。html
Asset | Size |
---|---|
bundle.main.js | 1.36MB |
隨之帶來的問題是用戶在屏幕上看到任何東西以前,必需要下載整個文件並運行它。若是用戶使用的是網絡鏈接很差的設備,這個過程可能須要很長時間。
Code splitting 就是把打包文件分割成爲更小的文件,容許用戶在他們須要的時候下載須要的代碼塊的一個方法。
例如,看看這個簡單的界面,咱們能夠識別出這個App中不須要初始載入的部分。vue
Code splitting 的關鍵就是異步組件(async components),這個組件的定義就是異步加載(包括它的模板,數據,方法等等)。
首先讓咱們用component API 即 Vue.component(name, definition) 聲明一個組件。不一樣於將定義對象做爲第二個參數,異步組件有一個函數,這個函數有兩個顯著的特色:webpack
Vue.component('async-component', (resolve) => {
resolve({
template: '<div>Async Component</div>',
props: [ 'myprop' ]
});
});
複製代碼
異步組件是 Code splitting 的第一步,由於咱們如今纔有了一個抽象的機制。web
咱們還須要 webpack 的幫助,假設咱們將組件定義抽象爲ES6模塊文件:bash
AsyncComponent.js網絡
export default {
template: '<div>Async Component</div>',
props: [ 'myprop' ]
}
複製代碼
咱們怎麼讓Vue.js加載它呢?你可能會想試試這樣的方法:架構
import AsyncComponent from './AsyncComponent.js'`;
Vue.component('async-component', AsyncComponent);
複製代碼
可是這是靜態的而且在編譯時解析,若是咱們想要得到Code splitting 的好處,咱們須要的是在運行的應用中動態地加載。app
目前,用JavaScript來動態的加載模塊是不可能的。可是,ECMAScript有一個動態模塊加載函數叫作 import() 。 Webpack已經有了一個import()的實現,並將其做爲一個代碼分割點,在建立包時,將所請求的模塊放入一個單獨的文件中(一個單獨的chunk,實際上,如今把它看做單獨的一個文件)。
import() 將文件名做爲一個參數並返回一個Promise。下面是咱們如何加載上面的模塊:異步
import(/* webpackChunkName: "async-component" */ './AsyncComponent.js')
.then((AsyncComponent) => {
console.log(AsyncComponent.default.template);
// Output: <div>Async Component</div>
});
複製代碼
注:若是你使用Babel,你須要添加 syntax-dynamic-import 插件***以便Babel能夠正確的解析。***async
如今,但你構建項目的時候,你會注意到這些模塊出如今它本身的文件中了:
Asset | Chuck Name |
---|---|
bundle.main.js | main |
bundle.0.js | async-component |
你能夠給動態導入的模塊加一個名字,讓它更容易識別;只需在文件名前面添加一個註釋,就像我在上面的例子中所作的那樣。
由於 import() 返回一個Promise,咱們能夠將它和 Vue 的異步組件功能結合使用。Webpack將單獨打包異步組件,並經過AJAX將其動態加載到應用程序中。
main.js
import Vue from 'vue';
Vue.component('async-component', (resolve) => {
import('./AsyncComponent.js')
.then((AsyncComponent) => {
resolve(AsyncComponent.default);
});
});
new Vue({
el: '#app'
});
複製代碼
index.html
<div id="app">
<p>This part is included in the page load</p>
<async-component></async-component>
</div>
<script src="bundle.main.js"></script>
複製代碼
頁面初始加載時:
<div id="app">
<p>This part is included in the page load</p>
</div>
複製代碼
當main.js運行的時候,它將啓動異步組件模塊的請求(這是自動實現的,由於 webpack 的 import() 包含了AJAX加載模塊的代碼)。
若是Ajax成功返回模塊,Promise 完成而且渲染組件,頁面將會被渲染成這樣:
<div id="app">
<p>This part is included in the page load</p>
<div>Async Component</div>
</div>
複製代碼
下圖能夠更好地幫助你理解:
Vue 實現 Code Splitting 的特殊方式就是使用 single file component。下面是使用single file component的代碼重構:
AsyncComponent.vue
<template>
<div>Async Component</div>
</template>
<script>
export default {
props: [ 'myprop' ]
}
</script>
複製代碼
導入的語法也更加簡潔
new Vue({
el: '#app',
components: {
AsyncComponent: () => import('./AsyncComponent.vue')
}
});
複製代碼
這是無關技術的部分,問題就是咱們怎麼爲一個app構建一個code splitting ?
最直接的方法就是按照界面來,好比,你的app上有兩個界面,一個home,一個about。這兩個界面是由兩個組件(home.vue about.vue)構成,那麼這兩個組件就能夠是拆分的點。
另外,你也能夠對任何有條件的組件(選項卡、彈窗、下拉菜單等等)或者是footer進行拆分。