本篇文章為大家展示了webpack2中怎么實(shí)現(xiàn)異步加載,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序定制開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了樂清免費(fèi)建站歡迎大家使用!
webpack提供的一個非常強(qiáng)大的功能就是code spliting(代碼切割)。
在webpack 1.x中提供了
require.ensure([], () => {
let module = require('./page1/module');
// do something
}, 'module1')利用require.ensure這個API使得webpack單獨(dú)將這個文件打包成一個可以異步加載的chunk.
具體的套路見我寫的另一篇blog: webpack分包及異步加載套路
一句話總結(jié)就是:
在輸出的runtime代碼中,包含了異步chunk的id及chunk name的映射關(guān)系。需要異步加載相應(yīng)的chunk時(shí),通過生成script標(biāo)簽,然后插入到DOM中完成chunk的加載。通過JSONP,runtime中定義好函數(shù),chunk加載完成后即會立即執(zhí)行這個函數(shù)。
從編譯生成后的代碼來看,webpack 1.x從chunk的加載到執(zhí)行的過程處理的比較粗糙,僅僅是通過添加script標(biāo)簽,異步加載chunk后,完成函數(shù)的執(zhí)行。
這個過程當(dāng)中,如果出現(xiàn)了chunk加載不成功時(shí),這種情況下應(yīng)該如何去容錯呢?
在webpack2中相比于webpack1.x在這個點(diǎn)的處理上是將chunk的加載包裹在了promise當(dāng)中,那么這個過程變的可控起來。具體的webpack2實(shí)現(xiàn)套路也是本文想要去說明的地方。
webpack提供的異步加載函數(shù)是
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
// runtime代碼里面只包含了入口的chunk
// 這個函數(shù)的主要作用:
// 1. 異步加載chunk
// 2. 提供對于chunk加載失敗或者處于加載中的處理
// 其中chunk加載狀態(tài)的判斷是根據(jù)installedChunks對象chunkId是數(shù)字0還是數(shù)組來進(jìn)行判斷的
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
// 數(shù)字0代表chunk加載成功
/******/ if(installedChunks[chunkId] === 0)
/******/ return Promise.resolve();
/******/ // an Promise means "currently loading".
// 如果installedChunks[chunkId]為一個數(shù)組
/******/ if(installedChunks[chunkId]) {
// 返回一個promise對象
/******/ return installedChunks[chunkId][2];
/******/ }
/******/ // start chunk loading
// 通過生成script標(biāo)簽來異步加載chunk.文件名是根據(jù)接受的chunkId來確認(rèn)的
/******/ var head = document.getElementsByTagName('head')[0];
/******/ var script = document.createElement('script');
/******/ script.type = 'text/javascript';
/******/ script.charset = 'utf-8';
/******/ script.async = true;
// 超時(shí)時(shí)間為120s
/******/ script.timeout = 120000;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
// 需要加載的文件名
/******/ script.src = __webpack_require__.p + "js/register/" + ({"2":"index"}[chunkId]||chunkId) + ".js";
// 120s的定時(shí)器,超時(shí)后觸發(fā)onScriptComplete回調(diào)
/******/ var timeout = setTimeout(onScriptComplete, 120000);
// chunk加載完畢后的回調(diào)
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
// 清空定時(shí)器
/******/ clearTimeout(timeout);
// 獲取這個chunk的加載狀態(tài)
// 若為數(shù)字0,表示加載成功
// 若為一個數(shù)組, 調(diào)用數(shù)組的第2個元素(第二個元素為promise內(nèi)傳入的reject函數(shù)),使得promise捕獲拋出的錯誤。reject(new Error('xxx'))
/******/ var chunk = installedChunks[chunkId];
/******/ if(chunk !== 0) {
/******/ if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
/******/ installedChunks[chunkId] = undefined;
/******/ }
/******/ };
// 每次需要進(jìn)行異步加載chunk時(shí),會將這個chunk的加載狀態(tài)進(jìn)行初始化為一個數(shù)組,并以key/value的形式保存在installedChunks里
// 這個數(shù)組為[resolve, reject, promise];
/******/ var promise = new Promise(function(resolve, reject) {
/******/ installedChunks[chunkId] = [resolve, reject];
/******/ });
/******/ installedChunks[chunkId][2] = promise;
/******/ head.appendChild(script);
//返回promise
/******/ return promise;
/******/ };我們再來看看路由配置文件編譯后生成的代碼index.js, 特別注意下__webpack_require__.e這個異步加載函數(shù):
Router
.home('path2')
.addRoute({
path: 'path2',
animate: 'zoomIn',
viewBox: '.public-path2-container',
template: __webpack_require__(5),
// 掛載controller
pageInit: function pageInit() {
var _this = this;
console.time('route async path2');
// 異步加載0.js(這個文件是webpack通過code spliting自己生成的文件名)
// 具體異步加載代碼的封裝見?分析
// 其中0.js包含了包含了path2這個路由下的業(yè)務(wù)代碼
// __webpack_require__.e(0) 起的作用僅為加載chunk以及提供對于chunk加載失敗錯誤的拋出
// 具體的業(yè)務(wù)代碼的觸發(fā)是通過__webpack_require_e(0).then(__webpack_require__.bind(null, 8)).then(function(module) { ... })進(jìn)行觸發(fā)
// __webpack_require__.bind(null, 8) 返回的是module[8]暴露出來的module
// 這段代碼執(zhí)行時(shí),首先初始化一個module對象
// module = {
// i: moduleId, // 模塊id
// l: false, // 加載狀態(tài)
// exports: {} // 需要暴露的對象
// }
// 通過異步加載的chunk最后暴露出來的對象是作為了module.exports.default屬性
// 因此在第二個方法中傳入的對象的default屬性才是你模塊8真正所暴露的對象
__webpack_require__.e/* import() */(0).then(__webpack_require__.bind(null, 8)).then(function (module) {
var controller = module.default;
Router.registerCtrl('path2', new controller(_this.viewBox));
// 添加錯誤處理函數(shù),用以捕獲前面可能拋出的錯誤
}).catch(function (e) {
return console.log('chunk loading failed');
});
},
// 進(jìn)入路由跳轉(zhuǎn)之前
beforeEnter: function beforeEnter() {},
// 路由跳轉(zhuǎn)前
beforeLeave: function beforeLeave() {}
})
.addRoute({
path: 'path3',
viewBox: '.public-path3-container',
animate: 'zoomIn',
template: __webpack_require__(6),
pageInit: function pageInit() {
var _this2 = this;
__webpack_require__.e/* import() */(1).then(__webpack_require__.bind(null, 9)).then(function (module) {
console.time('route async path3');
var controller = module.default;
Router.registerCtrl('path3', new controller(_this2.viewBox));
}).catch(function (e) {
return console.log('chunk loading failed');
});
},
beforeEnter: function beforeEnter() {},
beforeLeave: function beforeLeave() {}
});
Router.bootstrap();上述內(nèi)容就是webpack2中怎么實(shí)現(xiàn)異步加載,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當(dāng)前標(biāo)題:webpack2中怎么實(shí)現(xiàn)異步加載
文章出自:http://www.yijiale78.com/article22/gcsjcc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、標(biāo)簽優(yōu)化、用戶體驗(yàn)、商城網(wǎng)站、域名注冊、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)