前言
webpack将import(chunkId)打包成__webpack_require__.e(chunkId)。首先__webpack_require__.e****会创建一个promise,并且将该promise的resove函数缓存到installedChunks对象中,然后创建script标签加载资源。接着资源加载成功之后,资源中会自动调用webpackJsonpCallback,传入的参数格式是[[chunkId], {moduleId: () => {}}]。该函数做了两个处理:1. 将moduleId作为modules的key,将module函数添加到modules中;2. 调用installedChunks中保存的resolve函数,此时__webpack_require__.e的promise.all变成resolved状态。最终通过__webpack_require(moduleId)的方式返回最终的模块。
const installedChunks = {}; // 保存着promise的resolve函数,类似:{ [chunkId]: resolve }
function _webpack_repuire.e(chunkId) {
const promises = [];
const promise = new Promise(function(resolve) {
// 将resolve函数保存起来
installedChunks[chunkId] = resolve;
})
addScript(); // 创建script,异步加载资源。具体代码省略
return Promise.all(promises);
}
// 加载的js资源是一个函数执行,该函数在主文件中由webpack定义然后挂载到window上
webpackJsonpCallback([
[chunId],
{
moduleId: (module, __webpack_exports__, __webpack_require__) => {
__webpack_exports__["default"] = '我们到代码';
}
}
])
// 异步资源加载成功之后执行
function webpackJsonpCallback(data) {
const [chunks, moreModules] = data;
const resolves = [];
for(let i = 0; i <chunks.length; i++) {
// 将保存在installedChunks中的resolve函数,保存到resolves队列中,等待执行
const chunkId = chunks[i];
resolves.push(installedChunks[chunkId])
}
for(let moduleId in moreModules) {
// 将异步资源中到module函数添加到modules中。modules就是webpack的模块集合,是一个对象
// 数组,类似[{ [moduleId]: () => {} }]。
modules[moduleId] = moreModules[moduleId];
}
// 开始执行resolve,此时webpack_require.e中的promise.all变成resolved状态
while(resolves.length) {
resolves.shift()();
}
}
import('./utils.js').then(data => { console.log(data) });
// 会被打包成
__webpack_require__.e(chunkId).then(__webpack_require__.bind(null, moduleId)).then(data => { console.log(data) })
// __webpack_require__.e中的Promise.all返回之后,模块已经被注册到modules对象,然后
webpack_require就可以在modules上获取到模块函数,并且执行模块函数,然后返回模块的module.exports
对象。
至此,异步模块加载完成。