CommonJS模块加载器需用函数包装模块代码、维护缓存、解析路径并注入exports/require/module/__filename/__dirname。核心是通过vm.runInThisContext编译执行,同步读取文件,缓存模块输出,仅支持相对路径和.js文件。

CommonJS 模块系统本身不是 JavaScript 语言原生特性,而是 Node.js 在早期实现的一套同步模块规范。要“手动实现一个简单的 CommonJS 模块加载器”,本质是模拟 require、module、exports 和 global.__dirname/__filename 的行为,核心在于:**用函数包装模块代码、维护缓存、处理路径解析、注入上下文对象**。
1. 基础原理:模块被包装成函数执行
Node.js 实际把每个 .js 文件内容包裹进一个函数里,类似:
这样就能安全地提供局部变量(如 exports)并隔离作用域。我们实现加载器时,也要做这件事。
2. 核心步骤:手写 require 函数
下面是一个极简但可运行的 CommonJS 风格加载器(仅支持相对路径和 .js 扩展名,不处理循环依赖):
关键点说明:
- 用
Map缓存已加载模块,避免重复执行 - 用
fs.readFileSync同步读取文件(符合 CommonJS 同步语义) - 用
vm.runInThisContext或Function构造器编译模块字符串为函数 - 传入
exports、require、module、__filename、__dirname五个参数 - 模块内部的
module.exports即为返回值
3. 一个可运行的最小实现(Node.js 环境)
保存为 my-require.js:
(function(exports, require, module, __filename, __dirname) { ${code} })使用示例:
// math.js
module.exports.add = (a, b) => a + b;
<p>// main.js
const myRequire = require('./my-require');
const math = myRequire('./math.js');
console.log(math.add(2, 3)); // 5</p>4. 注意事项和限制
这个简易加载器适合理解原理,但生产中不能替代 Node.js 原生 require:
- 不支持
node_modules查找逻辑(比如从./node_modules逐级向上找) - 不处理 JSON、C++ 插件等其他模块类型
- 没有错误堆栈映射(原始行号会丢失)
- 不支持 ES 模块混用(
import/export) - 同步读取在浏览器环境不可用(需配合打包或 fetch + eval)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











