详细解析Webpack是怎么运行的(7)

关于第一点,我们回忆一下之前 __webpack_require__.e 的内容,此时 chunk 还处于「加载中」的状态,也就是说对应的 installedChunks[chunkId] 的值此时为[resolve, reject, promise]。 而这里,chunk 已经加载,但 promise 还未决议,于是 webpackJsonpCallback 内部定义了一个 resolves 变量用来收集 installedChunks 上的 resolve 并执行它。`

接下来说到第二点,就要涉及几个层面的缓存了。

首先是 chunk 层面,这里有两个相关操作,操作一将 installedChunks[chunkId] 置为 0 可以让 __webpack_require__.e在第二次加载同一 chunk 时返回一个立即决议的 promise(Promise.all([]));操作二将 chunk data 添加进 window["webpackJsonp"] 数组,可以在多入口模式时,方便地拿到已加载过的 chunk 缓存。通过以下代码实现:

/*** 缓存执行部分 ***/
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
// ...
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
var parentJsonpFunction = oldJsonpFunction;
/*** 缓存执行部分 ***/

/*** 缓存添加部分 ***/
function webpackJsonpCallback(data) {
 //...
 // 此处的 parentJsonpFunction 是 window["webpackJsonp"] 数组的原生 push
 if (parentJsonpFunction) parentJsonpFunction(data);
 //...
}
/*** 缓存添加部分 ***/

而在 modules 层面,chunk 中的 moreModules 被合入入口文件的modules 中,可供下一个微任务中的 __webpack_require__ 同步加载模块。

({
 "./src/index.js":
 (function (module, exports, __webpack_require__) {
  console.log('Hello webpack!');
  window.setTimeout(() => {
  __webpack_require__.e(0).then(__webpack_require__.bind(null, "./src/utils/math.js")).then(mathUtil => {
   console.log('1 + 2: ' + mathUtil.plus(1, 2));
  });
  }, 2000);
 })
});

__webpack_require__.e(0)返回的 promise 决议后,__webpack_require__.bind(null, "./src/utils/math.js") 可以加载到chunk携带的模块,并返回模块作为下一个微任务函数的入参,接下来就是 Webpack Loader 翻译过的其他业务代码了。

现在让我们把异步流程梳理一下:

更多Webpack的基础知识请点击下面的相关文章

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1508.html