利用webpack對代碼進行分割是懶加載的前提,懶加載就是異步調(diào)用組件,需要時候才下載(按需加載)。
為什么需要懶加載?
在單頁應用中,如果沒有應用懶加載,運用webpack打包后的文件將會異常的大,造成進入首頁時,需要加載的內(nèi)容過多,延時過長,不利于用戶體驗,而運用懶加載則可以將頁面進行劃分,需要的時候加載頁面,可以有效的分擔首頁所承擔的加載壓力,減少首頁加載用時。
vue開發(fā)過程中,我們會做出特別多特別多的組件,包括login,header,footer,main等等。
這樣使整個網(wǎng)站看起來就十分的龐大,當我們在打開網(wǎng)頁的時候,突然一下子把這些所有的組件加載上來,這么多的請求全部同時開始請求,勢必會造成網(wǎng)頁打開很慢,使客戶得到的是非常差勁的體驗。
因此,vue為我們專門設(shè)立了異步組件,通過異步組件,我們可以得到兩點好處:
1、 用不到的組件不會加載,因此網(wǎng)頁打開速度會很快,當你用到這個組件的時候,才會通過異步請求進行加載;
2、 緩存組件,通過異步加載的組件會緩存起來,當你下一次再用到這個組件時,絲毫不會有任何的疑遲,組件很快會從緩存中加載出來。
異步組件=原理同webpack的按需加載
好處:
1)按需加載,可以節(jié)省首次加載時間,提高速度,性能優(yōu)化
2)第一次加載完成會緩存
異步組件的描述:
Vue允許將組件定義為一個異步解析(加載)組件定義的工廠函數(shù),即Vue只在實際需要渲染組件時,才會觸發(fā)調(diào)用工廠函數(shù),并且將結(jié)果緩存起來,用于將來再次渲染。
!?。s:要使用異步組件,一個比較推薦的方式就是配合webpack代碼分離功能。
例子:(全局|局部)
法一:結(jié)合webpack
//1)全局:
Vue.component('component-name',function(resolve){
//require 語法告訴 webpack自動將編譯后的代碼分割成不同的塊
//這些塊將通過 Ajax 請求自動下載
require(['./my-async-componnet'],resolve)
})
//注冊全局組件名,但只有一個名字,沒有實體,相當于空的
//當需要這個組件時,調(diào)用上面的工廠函數(shù),觸發(fā)webpack的異步加載模塊方法
//然后異步請求一個模塊,請求成功后,這個模塊內(nèi)容即為組件實體部分,并對應地方渲染,加載內(nèi)容也緩存下來。
//2)局部
new Vue({
components: {
'component-name':function(resolve) {
require(['./my-component'], resolve)
}
}
})
法二:通過webpack2+es2015返回一個promise
//1)全局:
Vue.component('component-name',
()=> import('./my-async-componnet')
)
//2) 局部:
new Vue({
components: {
'component-name': () => import('./my-async-componnet')
}
})
高級異步組件(即處理加載狀態(tài))
工廠對象可以返回一個對象,對象里面的一些配置參數(shù)
const asyncComponent = () => ({
// 需要加載的組件 (應該是一個 `Promise` 對象)
component: import('./my-async-componnet'),
//異步加載時使用的組件(加載中的效果)
loading: loadingComponent,
//加載失敗時使用的組件
error: ErrorComponent,
//展示加載中組件的延時時間,默認200毫秒
delay: 200,
//超時時間,超過該時間顯示加載失敗的組件
timeout: 3000
})
單文件組件+vue-router案例:
2個組件:first、second代表2個頁面, 路由文件異步組件方式:
//傳統(tǒng)寫法:import First from '@/components/First'
方法一:
const first = () => import("../components/first.vue")
const second = () => import("../components/second.vue")
方法二:
const first = resolve => require.ensure([], () => resolve( require(../components/first.vue)), 'chunkname1')
const second = resolve => require.ensure([], () => resolve( require(../components/second.vue)), 'chunkname2')
//其余配置如以往一樣
const routes = [
{
path: '/',
component: first
},
{
path: '/',
component: second
}
]
webpack中利用require.ensure()實現(xiàn)按需加載
require.ensure()(webpack異步加載|代碼分割)
- 解釋1:把js模塊獨立導出一個個js文件,然后使用這個模塊時,webpack會構(gòu)造這個script dom元素,加入到document.head中,由瀏覽器自動發(fā)起異步請求這個js文件,再寫個回調(diào),去定義得到這個js文件后的業(yè)務(wù)邏輯。
- 解釋2:webpack 在編譯時,會靜態(tài)地解析代碼中的 require.ensure(),同時將模塊添加到一個分開的 chunk 當中。這個新的 chunk 會被 webpack 通過 jsonp 來按需加載。
require.ensure這個函數(shù)是一個代碼分離的分割線,表示 回調(diào)里面的require
是我們想要進行分割出去的,即require(’./baidumap.js’),把baidumap.js分割出去,形成一個webpack打包的單獨js文件。當然ensure里面也是可以寫一些同步的require的,如:
var sync = require('syncdemo.js') //下面ensure里面也用到
btn.click(function() {
require.ensure([], function() {
var map = require('./map.js') //map.js放在我們當前目錄下
//這個不會獨立出去,因為它已經(jīng)加載到模塊緩存中了
var sync = require('syncdemo.js')
})
})
===》ensure會把沒有使用過的require資源進行獨立分成成一個js文件
ensure語法及參數(shù)解釋
require.ensure(dependencies: string[], callback: function(require),chunkName:string)
- 第一個參數(shù):默認[],放置當前這個模塊所依賴的其他模塊。比如:假設(shè)A 和 B都是異步的,B中需要A,則B下載之前,先要下載A :require.ensure([‘A.js’], function...),!!!!需要注意:webpack會把參數(shù)里面的依賴異步模塊和當前的需要分離出去的異步模塊給一起打包成同一個js文件,這里可能會出現(xiàn)一個重復打包的問題, 假設(shè)A 和 B都是異步的, ensure A 中依賴B,ensure B中 依賴A,那么會生成兩個文件,都包含A和B模塊。
- 第二個參數(shù):當所有依賴都加載完成后,webpack會執(zhí)行這個回調(diào)函數(shù)。require對象的一個實現(xiàn)會作為一個參數(shù)傳遞給這個回調(diào)函數(shù)。因此,我們可以進一步require()依賴和其他模塊提供下一步的執(zhí)行。
- 第三個參數(shù),chunkname打包后代碼塊的名字:chunk提供給這個特定的require.ensure()的chunk的名稱。通過提供 require.ensure() 不同執(zhí)行點相同的名稱,我們可以保證所有的依賴都會一起放進相同的 文件束(bundle)。
使用 vue-cli構(gòu)建的項目,在 默認情況下 ,執(zhí)行 npm run build 會將所有的js代碼打包為一個整體。如果想要讓build之后的代碼更便于識別,可配置webpack代碼,單獨打包自己定義的名字(需要配置chunkFileName和publicPath)
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/', //是按需加載單獨打包出來的chunk是以publicPath為基準來存放的
filename: 'build.js',
chunkFilename: 'js/[name]-[chunkhash:8].js' //最終生成的路徑和名字
}
}


參考地址: