Webpack 构建的最小单位
Module 的集合,可通过 splitChunks
插件定义分包方式
假设存在一个模块 imported.js
,被入口文件 app.js
异步导入,文件结构与内容如下
// imported.js
export default {
test: 'this is test'
}
// app.js
(async () => {
const module = (await import("./imported"))
console.log(module) // Module: {default: { test: ... }}
})();
以上代码构建后,导入语句将被转换为
const test = (await __webpack_require__.e("src_imported_js").then(__webpack_require__.bind(__webpack_require__, "./src/imported.js")))
可以看出异步模块的加载首先要经过 __webpack_require__.e
处理,之后再由 __webpack_require__
加载模块并缓存
此函数需要传入一个 ChunkId
,再将其传入 __webpack_require__.f
内的每一个函数,等所有的promises 都 resolved 后,返回所有 promises resovled 的结果数组
__webpack_require__.f
内置了不同 Chunk 的加载器,每个加载器的签名都是 (chunkId, promises)
。之所以要传入 promises,是因为加载的 Chunk 可能还需要再加载其它的 Chunk
__webpack_require__.e = (chunkId) => {
return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
__webpack_require__.f[key](chunkId, promises);
return promises;
}, []));
};
这里暂时只关心 __webpack_require__.f
内其中一个异步 Chunk 加载函数,它的作用如下(进行了改写,不改变核心流程)
__webpack_require__.f.j = (chunkId, promises) => {
// JSONP chunk loading for javascript
var installedChunkData = installedChunks[chunkId] || undefined;
if (installedChunkData !== 0) { // 0 means "already installed".
// a Promise means "currently loading".
if (installedChunkData) {
promises.push(installedChunkData[2]);
} else {
// setup Promise in chunk cache
var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
promises.push(installedChunkData[2] = promise);
// start chunk loading
var error = new Error();
var loadingEnded = () => {
installedChunkData = installedChunks[chunkId];
if (installedChunkData !== 0) installedChunks[chunkId] = undefined;
if (installedChunkData) {
installedChunkData[1](error);
}
};
__webpack_require__.l(chunkUrl, loadingEnded, chunkId);
}
}
};
installedChunks[chunkId]
上。loadingEnded
,若 installedChunks[chunkId]
不为整数 0,则置空加载状态,并抛出错误__webpack_require__.l
正式异步加载 Chunk