亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

詳解webpack2異步加載套路

2024-05-06 16:46:07
字體:
來源:轉載
供稿:網友

webpack提供的一個非常強大的功能就是code spliting(代碼切割)。

在webpack 1.x中提供了

  require.ensure([], () => {    let module = require('./page1/module');    // do something  }, 'module1')

利用require.ensure這個API使得webpack單獨將這個文件打包成一個可以異步加載的chunk.

一句話總結就是:

在輸出的runtime代碼中,包含了異步chunk的id及chunk name的映射關系。需要異步加載相應的chunk時,通過生成script標簽,然后插入到DOM中完成chunk的加載。通過JSONP,runtime中定義好函數,chunk加載完成后即會立即執行這個函數。

從編譯生成后的代碼來看,webpack 1.x從chunk的加載到執行的過程處理的比較粗糙,僅僅是通過添加script標簽,異步加載chunk后,完成函數的執行。

這個過程當中,如果出現了chunk加載不成功時,這種情況下應該如何去容錯呢?

webpack2中相比于webpack1.x在這個點的處理上是將chunk的加載包裹在了promise當中,那么這個過程變的可控起來。具體的webpack2實現套路也是本文想要去說明的地方。

webpack提供的異步加載函數是

  /******/   // This file contains only the entry chunk./******/   // The chunk loading function for additional chunks      // runtime代碼里面只包含了入口的chunk      // 這個函數的主要作用:      // 1. 異步加載chunk      // 2. 提供對于chunk加載失敗或者處于加載中的處理      // 其中chunk加載狀態的判斷是根據installedChunks對象chunkId是數字0還是數組來進行判斷的/******/   __webpack_require__.e = function requireEnsure(chunkId) {        // 數字0代表chunk加載成功/******/     if(installedChunks[chunkId] === 0) /******/       return Promise.resolve();/******/     // an Promise means "currently loading".        // 如果installedChunks[chunkId]為一個數組/******/     if(installedChunks[chunkId]) {          // 返回一個promise對象/******/       return installedChunks[chunkId][2];/******/     }/******/     // start chunk loading        // 通過生成script標簽來異步加載chunk.文件名是根據接受的chunkId來確認的/******/     var head = document.getElementsByTagName('head')[0];/******/     var script = document.createElement('script');/******/     script.type = 'text/javascript';/******/     script.charset = 'utf-8';/******/     script.async = true;        // 超時時間為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的定時器,超時后觸發onScriptComplete回調/******/     var timeout = setTimeout(onScriptComplete, 120000);        // chunk加載完畢后的回調/******/     script.onerror = script.onload = onScriptComplete;/******/     function onScriptComplete() {/******/       // avoid mem leaks in IE./******/       script.onerror = script.onload = null;          // 清空定時器/******/       clearTimeout(timeout);          // 獲取這個chunk的加載狀態          // 若為數字0,表示加載成功          // 若為一個數組, 調用數組的第2個元素(第二個元素為promise內傳入的reject函數),使得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;/******/       }/******/     };                // 每次需要進行異步加載chunk時,會將這個chunk的加載狀態進行初始化為一個數組,并以key/value的形式保存在installedChunks里        // 這個數組為[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這個異步加載函數:

Router.home('path1').addRoute({  path: 'path1',  animate: 'zoomIn',  viewBox: '.public-path1-container',  template: __webpack_require__(5),  // 掛載controller  pageInit: function pageInit() {    var _this = this;    console.time('route async path1');    // 異步加載0.js(這個文件是webpack通過code spliting自己生成的文件名)    // 具體異步加載代碼的封裝見?分析    // 其中0.js包含了包含了path1這個路由下的業務代碼    // __webpack_require__.e(0) 起的作用僅為加載chunk以及提供對于chunk加載失敗錯誤的拋出    // 具體的業務代碼的觸發是通過__webpack_require_e(0).then(__webpack_require__.bind(null, 8)).then(function(module) { ... })進行觸發    // __webpack_require__.bind(null, 8) 返回的是module[8]暴露出來的module    // 這段代碼執行時,首先初始化一個module對象    // module = {    //    i: moduleId, // 模塊id    //    l: false,   // 加載狀態    //    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('path1', new controller(_this.viewBox));    // 添加錯誤處理函數,用以捕獲前面可能拋出的錯誤    }).catch(function (e) {      return console.log('chunk loading failed');    });  },  // 進入路由跳轉之前  beforeEnter: function beforeEnter() {},  // 路由跳轉前  beforeLeave: function beforeLeave() {}}).addRoute({  path: 'path2',  viewBox: '.public-path2-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 path2');      var controller = module.default;      Router.registerCtrl('path2', new controller(_this2.viewBox));    }).catch(function (e) {      return console.log('chunk loading failed');    });  },  beforeEnter: function beforeEnter() {},  beforeLeave: function beforeLeave() {}});Router.bootstrap();

總結一下就是:

webpack2相比于webpack1.x將異步加載chunk的過程封裝在了promise當中,如果chunk加載超時或者失敗會拋出錯誤,這時我們可以針對拋出的錯誤做相應的錯誤處理。

此外還應該注意下,webpack2異步加載chunk是基于原生的promise。如果部分環境暫時還不支持原生promise時需要提供polyfill。另外就是require.ensure可以接受第三個參數用以給chunk命名,但是import這個API沒有提供這個方法

更多的細節大家可以運行demo看下編譯后的代碼 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲视频在线观看| 国产亚洲成av人片在线观看桃| 国产成人av网| 91久久综合亚洲鲁鲁五月天| 亚洲一区二区久久久久久久| 国产精品亚洲视频在线观看| 欧美人与性动交| 国产一区视频在线播放| 亚洲色在线视频| 国产伦精品一区二区三区精品视频| 国产激情999| 红桃av永久久久| 国产剧情久久久久久| 性欧美xxxx交| 18性欧美xxxⅹ性满足| 欧美黄色小视频| 97香蕉超级碰碰久久免费的优势| 97精品久久久| 国产精品成人国产乱一区| 最近中文字幕2019免费| 97精品欧美一区二区三区| 欧美小视频在线| 中文字幕欧美亚洲| 九九精品视频在线| 91精品视频在线播放| 有码中文亚洲精品| 欧美高清视频免费观看| 亚洲天堂色网站| 日本欧美在线视频| 一区二区欧美久久| 亚洲女在线观看| 激情av一区二区| 日韩精品中文字幕久久臀| 亚洲成人网av| 亚洲电影在线看| 国产精品久久久久久中文字| 高清视频欧美一级| 亚洲的天堂在线中文字幕| 国产欧美婷婷中文| 久久精品视频在线观看| 日韩美女福利视频| 奇米4444一区二区三区| 亚洲一区二区三区777| 精品综合久久久久久97| 日韩电影中文字幕一区| 日韩一区二区av| 奇门遁甲1982国语版免费观看高清| 日韩免费视频在线观看| 最近2019免费中文字幕视频三| 国产在线一区二区三区| 欧美激情一区二区久久久| 中文字幕精品久久久久| 亚洲aaa激情| 91美女高潮出水| 亚洲伊人第一页| 亚洲一级黄色片| xvideos亚洲人网站| 一级做a爰片久久毛片美女图片| 亚洲第一天堂无码专区| 欧美性色视频在线| 国产精品久久久久久久久久久久久久| 国产一区二区三区视频| 伊人亚洲福利一区二区三区| 亚洲天堂av在线免费| 日韩免费看的电影电视剧大全| 亚洲国产一区二区三区四区| 成人做爰www免费看视频网站| 91成人在线视频| 日韩成人高清在线| 第一福利永久视频精品| 亚洲精品国产精品自产a区红杏吧| 欧美大片欧美激情性色a∨久久| 成人免费网站在线观看| 亚洲网址你懂得| 在线观看国产成人av片| 91亚洲精品在线| 91久久久久久久久久久久久| 国产视频欧美视频| 精品伊人久久97| 欧美日本亚洲视频| 成人福利在线视频| 成人免费视频网址| 久久精品在线播放| 久久久在线视频| 亚洲国产成人在线播放| 欧美日韩亚洲高清| 91亚洲精品一区二区| 国产精品免费在线免费| 国产精品1区2区在线观看| 91网站免费看| 欧美一区视频在线| 亚洲精品成人久久久| 91精品视频网站| 69av在线视频| 欧美成人四级hd版| 久久久精品视频在线观看| 日韩电影免费观看在线观看| 亚洲性日韩精品一区二区| 国产亚洲一区精品| 亚洲无亚洲人成网站77777| 国产精品久久精品| 国产欧美日韩丝袜精品一区| 亚洲成人免费网站| 久久国产精品电影| 国产精品久久999| 欧美日韩高清在线观看| 久久精品国产久精国产思思| 亚洲成av人乱码色午夜| 亚洲第一区在线观看| 久久天堂av综合合色| 色悠久久久久综合先锋影音下载| 欧美高清视频在线| 久久久久久久久综合| 亚洲欧美国产一本综合首页| 久久精品成人动漫| 日韩欧美国产骚| 尤物yw午夜国产精品视频明星| 久久艳片www.17c.com| 国产精品视频免费在线| 色偷偷亚洲男人天堂| 国产日韩欧美自拍| 91精品免费看| 97国产在线视频| 亚洲精品乱码久久久久久金桔影视| 国产精品久久久久久久久久久久久| 欧美日韩美女视频| 亚洲天堂av在线播放| 色综合影院在线| 日韩欧美黄色动漫| 国产成人av网址| 69久久夜色精品国产7777| 国产免费一区二区三区香蕉精| 不卡在线观看电视剧完整版| 欧美日韩中文字幕| 日韩在线精品视频| 欧美视频专区一二在线观看| 国产视频福利一区| 亚洲精品一区二区三区婷婷月| 日韩av一卡二卡| 亚洲人成网在线播放| 欧美日韩免费区域视频在线观看| 国产专区欧美专区| 精品国产一区二区三区久久| 日韩欧美在线看| 久久久久久亚洲精品| 久久精品视频中文字幕| 伊人男人综合视频网| 欧美性精品220| 亚洲美女av在线| 亚洲аv电影天堂网| 中文字幕日韩高清| 另类色图亚洲色图| 午夜精品久久久久久99热软件| 欧美俄罗斯性视频| 久久青草福利网站| 亚洲精品久久7777777| 午夜精品久久久久久久白皮肤| 亚洲国产小视频在线观看| 国产亚洲欧美日韩精品| 欧美日韩高清在线观看| 精品久久久久久久大神国产| 欧美黑人国产人伦爽爽爽| 欧美高跟鞋交xxxxhd| 日韩在线视频网站|