✅ moduleNamespace
函数
用于生成访问模块命名空间的表达式(同步)。
module
:要访问的模块对象,类型为Module
chunkGraph
:Webpack 内部的 chunkGraph 实例,用于获取模块 ID 等信息request
:模块的请求路径,用于注释和调试信息strict
(可选):是否处于 strict ESM 模式,影响导出类型判断weak
(可选):是否为弱依赖,若模块 ID 不存在则生成错误代码而非抛出异常runtimeRequirements
(可选):传入后,会被填充所需的运行时代码(如__webpack_require__
,__webpack_require__.n
, 等)- 返回值:一个用于访问该模块命名空间的 JS 表达式字符串
✅ moduleNamespacePromise
函数
用于生成异步访问模块命名空间的 Promise 表达式。
chunkGraph
:Webpack 的 ChunkGraph 实例block
(可选):异步依赖块(如import()
),类型为AsyncDependenciesBlock
module
:目标模块对象,类型为Module
request
:模块请求路径,主要用于生成注释message
:用于生成注释的信息,提示加载内容strict
(可选):是否为 strict 模式,影响导出类型处理weak
(可选):是否为弱依赖,决定是否在模块 ID 缺失时生成警告代码runtimeRequirements
(可选):用于收集运行时依赖- 返回值 :一个 Promise 表达式,最终
.then()
得到模块命名空间对象
js
/**
* 根据模块信息生成访问该模块命名空间对象的表达式字符串。
*
* @param {Object} options 配置项
* @param {Module} options.module 当前依赖的模块
* @param {ChunkGraph} options.chunkGraph ChunkGraph 实例,用于获取模块 ID 等信息
* @param {string} options.request 当前模块请求路径,用于生成注释
* @param {boolean=} options.strict 是否开启 strict ESM 模式(影响 exportsType 判断)
* @param {boolean=} options.weak 是否是弱依赖(模块可能不存在)
* @param {RuntimeRequirements=} options.runtimeRequirements 若传入,则会被填充依赖的运行时变量
* @returns {string} 表达式字符串,用于访问模块命名空间(如 require(), __webpack_require__, fakeNamespace 等)
*/
moduleNamespace({
module,
chunkGraph,
request,
strict,
weak,
runtimeRequirements
}) {
// 模块不存在时,返回缺失模块的表达式
if (!module) {
return this.missingModule({ request });
}
// 模块存在但未被分配 moduleId
if (chunkGraph.getModuleId(module) === null) {
if (weak) {
// 弱依赖可以容忍没有 id,返回一个可报错表达式
return this.weakError({
module,
chunkGraph,
request,
type: "expression"
});
}
// 非弱依赖没有 id 说明是构建错误
throw new Error(
`RuntimeTemplate.moduleNamespace(): ${noModuleIdErrorMessage(
module,
chunkGraph
)}`
);
}
// 获取模块 ID 的表达式
const moduleId = this.moduleId({
module,
chunkGraph,
request,
weak
});
// 获取模块的导出类型(例如 default-only, namespace 等)
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
switch (exportsType) {
case "namespace":
// 直接返回模块原始对象(即命名空间对象)
return this.moduleRaw({
module,
chunkGraph,
request,
weak,
runtimeRequirements
});
case "default-with-named":
// 模块既有默认导出也有命名导出,构造 fake 命名空间,标志为 3
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
case "default-only":
// 只有默认导出,标志为 1
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
case "dynamic":
// 动态导出(运行时决定),标志为 7
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
}
}
/**
* 生成异步访问模块命名空间对象的 Promise 表达式。
*
* @param {Object} options 配置项
* @param {ChunkGraph} options.chunkGraph ChunkGraph 实例
* @param {AsyncDependenciesBlock=} options.block 当前模块所在的异步依赖块
* @param {Module} options.module 需要异步加载的模块
* @param {string} options.request 请求字符串,用于注释
* @param {string} options.message 异步模块加载时用于注释的提示信息
* @param {boolean=} options.strict 是否为 strict 模式,影响模块 exportsType 判断
* @param {boolean=} options.weak 是否为弱依赖(不强制要求模块存在)
* @param {RuntimeRequirements=} options.runtimeRequirements 若传入,则会被填充依赖的运行时变量
* @returns {string} 返回一个 Promise 表达式,最终 `.then` 得到模块的命名空间对象
*/
moduleNamespacePromise({
chunkGraph,
block,
module,
request,
message,
strict,
weak,
runtimeRequirements
}) {
// 模块不存在,返回缺失模块的 Promise 表达式
if (!module) {
return this.missingModulePromise({ request });
}
// 获取模块 ID
const moduleId = chunkGraph.getModuleId(module);
if (moduleId === null) {
if (weak) {
// 弱依赖可以容忍没有 id,返回运行时报错表达式
return this.weakError({
module,
chunkGraph,
request,
type: "promise"
});
}
// 非弱依赖没有 id 抛出异常
throw new Error(
`RuntimeTemplate.moduleNamespacePromise(): ${noModuleIdErrorMessage(
module,
chunkGraph
)}`
);
}
// 获取异步加载该模块的 Promise 表达式(如 import())
const promise = this.blockPromise({
chunkGraph,
block,
message,
runtimeRequirements
});
let appending; // 用于拼接的 .then 链
let idExpr = JSON.stringify(moduleId); // moduleId 的 JSON 表达形式
const comment = this.comment({ request }); // 注释字符串
let header = ""; // 弱依赖时的前置 ID 检查逻辑代码
if (weak) {
// 如果 id 表达式太长则使用临时变量
if (idExpr.length > 8) {
header += `var id = ${idExpr}; `;
idExpr = "id";
}
// 添加对 Runtime.moduleFactories 的依赖
runtimeRequirements.add(RuntimeGlobals.moduleFactories);
// 添加工厂存在性检查逻辑
header += `if(!${
RuntimeGlobals.moduleFactories
}[${idExpr}]) { ${this.weakError({
module,
chunkGraph,
request,
idExpr,
type: "statements"
})} } `;
}
// 获取模块 ID 的表达式
const moduleIdExpr = this.moduleId({
module,
chunkGraph,
request,
weak
});
// 获取模块导出类型
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
let fakeType = 16; // 标记为 async fake namespace 对象
switch (exportsType) {
case "namespace":
if (header) {
// 有弱依赖检查逻辑,生成包裹的 .then
const rawModule = this.moduleRaw({
module,
chunkGraph,
request,
weak,
runtimeRequirements
});
appending = `.then(${this.basicFunction(
"",
`${header}return ${rawModule};`
)})`;
} else {
// 否则直接 require 加载
runtimeRequirements.add(RuntimeGlobals.require);
appending = `.then(${RuntimeGlobals.require}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}))`;
}
break;
case "dynamic":
fakeType |= 4;
// fallthrough
case "default-with-named":
fakeType |= 2;
// fallthrough
case "default-only":
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
if (chunkGraph.moduleGraph.isAsync(module)) {
// 异步模块需要两层 then
if (header) {
const rawModule = this.moduleRaw({
module,
chunkGraph,
request,
weak,
runtimeRequirements
});
appending = `.then(${this.basicFunction(
"",
`${header}return ${rawModule};`
)})`;
} else {
runtimeRequirements.add(RuntimeGlobals.require);
appending = `.then(${RuntimeGlobals.require}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}))`;
}
appending += `.then(${this.returningFunction(
`${RuntimeGlobals.createFakeNamespaceObject}(m, ${fakeType})`,
"m"
)})`;
} else {
// 同步模块一层 then 即可
fakeType |= 1;
if (header) {
const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
appending = `.then(${this.basicFunction(
"",
`${header}return ${returnExpression};`
)})`;
} else {
appending = `.then(${RuntimeGlobals.createFakeNamespaceObject}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}, ${fakeType}))`;
}
}
break;
}
// 返回最终组合好的 Promise 表达式
return `${promise || "Promise.resolve()"}${appending}`;
}