webpack 运行时模版 第 三 节 /lib/RuntimeTemplate.js

错误处理与模块缺失相关方法

  • throwMissingModuleErrorBlock({ request })

    • 生成同步语句的抛错代码块。
    • 返回 var e = new Error(...); throw e; 形式。
  • throwMissingModuleErrorFunction({ request })

    • 返回一个函数定义,内部执行 throwMissingModuleErrorBlock()
    • 用于异步场景。
  • missingModule({ request })

    • 返回一个执行 throwMissingModuleErrorFunction() 的 IIFE 表达式。
    • 用于作为表达式引发错误。
  • missingModuleStatement({ request })

    • 返回完整语句版本的错误抛出,包括 ;\n
    • 用于代码块中。
  • missingModulePromise({ request })

    • 返回基于 Promise.resolve().then(...) 的异步错误抛出。
    • 用于动态 import 异步模块失败的场景。
  • weakError({ module, chunkGraph, request, idExpr, type })

    • 用于生成"弱依赖"缺失时的错误提示代码。
    • 支持三种输出形式:statements(语句)、promise(异步)、expression(表达式)。

🔹 模块 ID 与模块导入相关方法

  • moduleId({ module, chunkGraph, request, weak })

    • 返回模块 ID 字符串(如 "123"),并带上注释。
    • 如果模块为弱依赖且无 ID,返回 null /* weak dependency */
    • 若不是弱依赖但无 ID,则抛出异常。
  • moduleRaw({ module, chunkGraph, request, weak, runtimeRequirements })

    • 返回 require(moduleId) 表达式。
    • 同时添加 RuntimeGlobals.require 到依赖集合中。
    • 处理模块缺失和弱依赖报错。
  • moduleExports(...)

    • 等价于调用 moduleRaw()
    • 用于获取模块导出的表达式。

🔹 注释生成工具

  • comment({ request, chunkName, chunkReason, message, exportName })

    • 生成模块注释字符串。
    • 根据 outputOptions.pathinfo 决定注释内容丰富程度。
    • 返回多行或单行注释样式。
js 复制代码
/**
 * 生成模块信息注释字符串
 */
comment({ request, chunkName, chunkReason, message, exportName }) {
	let content;
	if (this.outputOptions.pathinfo) {
		// 如果配置开启 pathinfo,包含更多字段:message、request、chunkName、chunkReason
		content = [message, request, chunkName, chunkReason]
			.filter(Boolean) // 过滤掉 undefined/null/空串
			.map(item => this.requestShortener.shorten(item)) // 使用 requestShortener 缩短
			.join(" | "); // 用 | 分隔
	} else {
		// 未开启 pathinfo,只包含部分字段
		content = [message, chunkName, chunkReason]
			.filter(Boolean)
			.map(item => this.requestShortener.shorten(item))
			.join(" | ");
	}
	if (!content) return ""; // 如果没生成内容则返回空字符串
	if (this.outputOptions.pathinfo) {
		// pathinfo 开启时使用多行注释风格
		return `${Template.toComment(content)} `;
	}
	// 否则使用单行注释
	return `${Template.toNormalComment(content)} `;
}

/**
 * 生成缺失模块的错误语句代码块(用于同步语句)
 */
throwMissingModuleErrorBlock({ request }) {
	const err = `Cannot find module '${request}'`; // 构建错误信息文本
	return `var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND'; throw e;`; // 返回 JS 错误抛出代码
}

/**
 * 生成一个函数体用于抛出缺失模块错误(用于异步调用中)
 */
throwMissingModuleErrorFunction({ request }) {
	return `function webpackMissingModule() { ${this.throwMissingModuleErrorBlock({ request })} }`; // 返回一个函数定义字符串
}

/**
 * 使用 IIFE(立即执行函数表达式)封装错误抛出(用于表达式场景)
 */
missingModule({ request }) {
	return `Object(${this.throwMissingModuleErrorFunction({ request })}())`; // 执行错误函数返回结果作为对象表达式
}

/**
 * 返回缺失模块抛错语句,带分号和换行(用于生成语句块)
 */
missingModuleStatement({ request }) {
	return `${this.missingModule({ request })};\n`;
}

/**
 * 返回一个 Promise 封装的缺失模块错误(用于动态 import 场景)
 */
missingModulePromise({ request }) {
	return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({ request })})`; // 异步抛错函数作为 then 回调
}

/**
 * 生成针对"弱依赖"模块缺失的错误抛出代码(支持三种形式)
 */
weakError({ module, chunkGraph, request, idExpr, type }) {
	const moduleId = chunkGraph.getModuleId(module); // 获取模块 ID
	const errorMessage =
		moduleId === null
			? JSON.stringify("Module is not available (weak dependency)") // ID 为空,使用默认错误提示
			: idExpr
				? `"Module '" + ${idExpr} + "' is not available (weak dependency)"` // 自定义表达式形式
				: JSON.stringify(`Module '${moduleId}' is not available (weak dependency)`); // 正常 ID 错误信息
	const comment = request ? `${Template.toNormalComment(request)} ` : ""; // 加上注释
	const errorStatements = `var e = new Error(${errorMessage}); ${comment}e.code = 'MODULE_NOT_FOUND'; throw e;`; // 构造错误抛出代码块
	switch (type) {
		case "statements":
			return errorStatements; // 返回纯语句形式
		case "promise":
			return `Promise.resolve().then(${this.basicFunction("", errorStatements)})`; // 封装为 Promise 形式
		case "expression":
			return this.iife("", errorStatements); // 封装为 IIFE 表达式形式
	}
}

/**
 * 生成模块 ID 的字符串表达式
 */
moduleId({ module, chunkGraph, request, weak }) {
	if (!module) {
		return this.missingModule({ request }); // 模块不存在,返回缺失模块表达式
	}
	const moduleId = chunkGraph.getModuleId(module); // 获取模块 ID
	if (moduleId === null) {
		if (weak) {
			return "null /* weak dependency, without id */"; // 弱依赖无 ID 返回 null
		}
		// 非弱依赖却没有 ID 抛出错误
		throw new Error(`RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(module, chunkGraph)}`);
	}
	// 返回模块 ID + 注释
	return `${this.comment({ request })}${JSON.stringify(moduleId)}`;
}

/**
 * 返回 require(moduleId) 的表达式(并处理弱依赖缺失情况)
 */
moduleRaw({ module, chunkGraph, request, weak, runtimeRequirements }) {
	if (!module) {
		return this.missingModule({ request }); // 模块不存在返回错误
	}
	const moduleId = chunkGraph.getModuleId(module);
	if (moduleId === null) {
		if (weak) {
			// 弱依赖但无 ID,返回错误表达式形式
			return this.weakError({ module, chunkGraph, request, type: "expression" });
		}
		// 非弱依赖却无 ID 抛出异常
		throw new Error(`RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(module, chunkGraph)}`);
	}
	runtimeRequirements.add(RuntimeGlobals.require); // 添加运行时代码中 require 的依赖
	return `${RuntimeGlobals.require}(${this.moduleId({ module, chunkGraph, request, weak })})`; // 返回 require(moduleId)
}

/**
 * 返回模块导出表达式(实际就是调用 moduleRaw)
 */
moduleExports({ module, chunkGraph, request, weak, runtimeRequirements }) {
	return this.moduleRaw({ module, chunkGraph, request, weak, runtimeRequirements });
}
相关推荐
昔冰_G5 分钟前
解锁webpack:对html、css、js及图片资源的抽离打包处理
前端·javascript·css·webpack·npm·html·打包
萌萌哒草头将军12 分钟前
🚀 REST API 还是 ✈️ GraphQL ❓
前端·vue.js·react.js
just小千25 分钟前
重学React(一):描述UI
前端·react.js·ui
fakaifa43 分钟前
【最新版】沃德代驾源码全开源+前端uniapp
前端·小程序·uni-app·开源·php·沃德代驾·代驾小程序
清羽_ls1 小时前
leetcode-位运算
前端·算法·leetcode·位运算
李菠菜1 小时前
利用Nginx实现高性能的前端打点采集服务(支持GET和POST)
linux·前端·nginx
lilye661 小时前
精益数据分析(6/126):深入理解精益分析的核心要点
前端·人工智能·数据分析
Apifox1 小时前
Apifox 4月更新|Apifox在线文档支持LLMs.txt、评论支持使用@提及成员、支持为团队配置「IP 允许访问名单」
前端·后端·ai编程
Jolyne_1 小时前
搭建公司前端脚手架
前端·架构·前端框架
hang_bro1 小时前
el-tree的动态加载问题与解决
前端·javascript·vue.js