利用webpack對代碼進(jìn)行分割是懶加載的前提醉顽,懶加載就是異步調(diào)用組件,需要時(shí)候才下載(按需加載)平挑。
為什么需要懶加載?
在單頁應(yīng)用中游添,如果沒有應(yīng)用懶加載,運(yùn)用webpack打包后的文件將會(huì)異常的大通熄,造成進(jìn)入首頁時(shí)唆涝,需要加載的內(nèi)容過多,延時(shí)過長棠隐,不利于用戶體驗(yàn)石抡,而運(yùn)用懶加載則可以將頁面進(jìn)行劃分,需要的時(shí)候加載頁面助泽,可以有效的分擔(dān)首頁所承擔(dān)的加載壓力,減少首頁加載用時(shí)嚎京。
vue開發(fā)過程中嗡贺,我們會(huì)做出特別多特別多的組件,包括login,header,footer,main等等鞍帝。
這樣使整個(gè)網(wǎng)站看起來就十分的龐大诫睬,當(dāng)我們在打開網(wǎng)頁的時(shí)候,突然一下子把這些所有的組件加載上來帕涌,這么多的請求全部同時(shí)開始請求摄凡,勢必會(huì)造成網(wǎng)頁打開很慢,使客戶得到的是非常差勁的體驗(yàn)蚓曼。
因此亲澡,vue為我們專門設(shè)立了異步組件,通過異步組件纫版,我們可以得到兩點(diǎn)好處:
1床绪、 用不到的組件不會(huì)加載,因此網(wǎng)頁打開速度會(huì)很快,當(dāng)你用到這個(gè)組件的時(shí)候癞己,才會(huì)通過異步請求進(jìn)行加載膀斋;
2、 緩存組件痹雅,通過異步加載的組件會(huì)緩存起來仰担,當(dāng)你下一次再用到這個(gè)組件時(shí),絲毫不會(huì)有任何的疑遲绩社,組件很快會(huì)從緩存中加載出來惰匙。
異步組件=原理同webpack的按需加載
好處:
1)按需加載,可以節(jié)省首次加載時(shí)間铃将,提高速度项鬼,性能優(yōu)化
2)第一次加載完成會(huì)緩存
異步組件的描述:
Vue允許將組件定義為一個(gè)異步解析(加載)組件定義的工廠函數(shù),即Vue只在實(shí)際需要渲染組件時(shí)劲阎,才會(huì)觸發(fā)調(diào)用工廠函數(shù)绘盟,并且將結(jié)果緩存起來,用于將來再次渲染悯仙。
A湔薄!锡垄!ps:要使用異步組件沦零,一個(gè)比較推薦的方式就是配合webpack代碼分離功能。
例子:(全局|局部)
法一:結(jié)合webpack
//1)全局:
Vue.component('component-name',function(resolve){
//require 語法告訴 webpack自動(dòng)將編譯后的代碼分割成不同的塊
//這些塊將通過 Ajax 請求自動(dòng)下載
require(['./my-async-componnet'],resolve)
})
//注冊全局組件名货岭,但只有一個(gè)名字路操,沒有實(shí)體,相當(dāng)于空的
//當(dāng)需要這個(gè)組件時(shí)千贯,調(diào)用上面的工廠函數(shù)屯仗,觸發(fā)webpack的異步加載模塊方法
//然后異步請求一個(gè)模塊,請求成功后搔谴,這個(gè)模塊內(nèi)容即為組件實(shí)體部分魁袜,并對應(yīng)地方渲染,加載內(nèi)容也緩存下來敦第。
//2)局部
new Vue({
components: {
'component-name':function(resolve) {
require(['./my-component'], resolve)
}
}
})
法二:通過webpack2+es2015返回一個(gè)promise
//1)全局:
Vue.component('component-name',
()=> import('./my-async-componnet')
)
//2) 局部:
new Vue({
components: {
'component-name': () => import('./my-async-componnet')
}
})
高級異步組件(即處理加載狀態(tài))
工廠對象可以返回一個(gè)對象峰弹,對象里面的一些配置參數(shù)
const asyncComponent = () => ({
// 需要加載的組件 (應(yīng)該是一個(gè) `Promise` 對象)
component: import('./my-async-componnet'),
//異步加載時(shí)使用的組件(加載中的效果)
loading: loadingComponent,
//加載失敗時(shí)使用的組件
error: ErrorComponent,
//展示加載中組件的延時(shí)時(shí)間,默認(rèn)200毫秒
delay: 200,
//超時(shí)時(shí)間芜果,超過該時(shí)間顯示加載失敗的組件
timeout: 3000
})
單文件組件+vue-router案例:
2個(gè)組件:first鞠呈、second代表2個(gè)頁面, 路由文件異步組件方式:
//傳統(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()實(shí)現(xiàn)按需加載
require.ensure()(webpack異步加載|代碼分割)
- 解釋1:把js模塊獨(dú)立導(dǎo)出一個(gè)個(gè)js文件,然后使用這個(gè)模塊時(shí)师幕,webpack會(huì)構(gòu)造這個(gè)script dom元素粟按,加入到document.head中诬滩,由瀏覽器自動(dòng)發(fā)起異步請求這個(gè)js文件,再寫個(gè)回調(diào)灭将,去定義得到這個(gè)js文件后的業(yè)務(wù)邏輯疼鸟。
- 解釋2:webpack 在編譯時(shí),會(huì)靜態(tài)地解析代碼中的 require.ensure()庙曙,同時(shí)將模塊添加到一個(gè)分開的 chunk 當(dāng)中空镜。這個(gè)新的 chunk 會(huì)被 webpack 通過 jsonp 來按需加載。
require.ensure這個(gè)函數(shù)是一個(gè)代碼分離的分割線捌朴,表示 回調(diào)里面的require
是我們想要進(jìn)行分割出去的吴攒,即require(’./baidumap.js’),把baidumap.js分割出去砂蔽,形成一個(gè)webpack打包的單獨(dú)js文件洼怔。當(dāng)然ensure里面也是可以寫一些同步的require的,如:
var sync = require('syncdemo.js') //下面ensure里面也用到
btn.click(function() {
require.ensure([], function() {
var map = require('./map.js') //map.js放在我們當(dāng)前目錄下
//這個(gè)不會(huì)獨(dú)立出去左驾,因?yàn)樗呀?jīng)加載到模塊緩存中了
var sync = require('syncdemo.js')
})
})
===》ensure會(huì)把沒有使用過的require資源進(jìn)行獨(dú)立分成成一個(gè)js文件
ensure語法及參數(shù)解釋
require.ensure(dependencies: string[], callback: function(require),chunkName:string)
- 第一個(gè)參數(shù):默認(rèn)[],放置當(dāng)前這個(gè)模塊所依賴的其他模塊镣隶。比如:假設(shè)A 和 B都是異步的,B中需要A诡右,則B下載之前安岂,先要下載A :require.ensure([‘A.js’], function...),!!!!需要注意:webpack會(huì)把參數(shù)里面的依賴異步模塊和當(dāng)前的需要分離出去的異步模塊給一起打包成同一個(gè)js文件,這里可能會(huì)出現(xiàn)一個(gè)重復(fù)打包的問題帆吻, 假設(shè)A 和 B都是異步的域那, ensure A 中依賴B,ensure B中 依賴A猜煮,那么會(huì)生成兩個(gè)文件次员,都包含A和B模塊。
- 第二個(gè)參數(shù):當(dāng)所有依賴都加載完成后友瘤,webpack會(huì)執(zhí)行這個(gè)回調(diào)函數(shù)翠肘。require對象的一個(gè)實(shí)現(xiàn)會(huì)作為一個(gè)參數(shù)傳遞給這個(gè)回調(diào)函數(shù)。因此辫秧,我們可以進(jìn)一步require()依賴和其他模塊提供下一步的執(zhí)行。
- 第三個(gè)參數(shù)被丧,chunkname打包后代碼塊的名字:chunk提供給這個(gè)特定的require.ensure()的chunk的名稱盟戏。通過提供 require.ensure() 不同執(zhí)行點(diǎn)相同的名稱,我們可以保證所有的依賴都會(huì)一起放進(jìn)相同的 文件束(bundle)甥桂。
使用 vue-cli構(gòu)建的項(xiàng)目,在 默認(rèn)情況下 ,執(zhí)行 npm run build 會(huì)將所有的js代碼打包為一個(gè)整體柿究。如果想要讓build之后的代碼更便于識(shí)別,可配置webpack代碼黄选,單獨(dú)打包自己定義的名字(需要配置chunkFileName和publicPath)
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/', //是按需加載單獨(dú)打包出來的chunk是以publicPath為基準(zhǔn)來存放的
filename: 'build.js',
chunkFilename: 'js/[name]-[chunkhash:8].js' //最終生成的路徑和名字
}
}
參考地址: