Node.js 模块导入的基本流程,主要是 CommonJS 模块加载机制 (即使用 require()
)的内部执行步骤。下面我用清晰的结构给你梳理一下这个过程:
✅ Node.js 模块导入的基本流程(使用 require()
)
js
const someModule = require('./someModule');
👣 加载流程详解:
① 解析模块路径
- Node.js 会先判断传入的是:
- 核心模块 (如
fs
,http
等); - 第三方模块(node_modules 中找);
- 相对路径模块 (以
./
或../
开头); - 绝对路径模块 (如
/Users/...
)。
- 核心模块 (如
② 定位文件(模块路径解析)
- 以相对路径为例:
require('./someModule')
,Node.js 会尝试依次查找以下几种形式:
bash
./someModule.js
./someModule.json
./someModule.node
./someModule/index.js # 如果是目录
③ 缓存检查
- Node.js 会先查看该模块是否已在 缓存 中(
require.cache
)。 - 如果存在缓存,则直接返回缓存结果(即模块导出的对象)。
④ 编译模块
- Node.js 根据不同文件类型执行不同的加载方式:
文件类型 | 加载方式 |
---|---|
.js |
作为 JavaScript 代码加载(包一层函数) |
.json |
使用 JSON.parse() 解析为对象 |
.node |
使用 C++ 插件方式加载(动态链接库) |
- 对于
.js
文件,Node.js 会将模块代码包装成如下形式:
js
(function(exports, require, module, __filename, __dirname) {
// 原始模块代码
})
这叫做 模块包装(Module Wrapper),让模块拥有自己的作用域。
⑤ 执行模块代码
- 在模块包装完成后,Node.js 执行模块代码,并把
module.exports
作为结果返回。
⑥ 返回 exports
对象
- 最终,
require()
返回的是module.exports
的内容。
💡 一个完整的生命周期图示(简略):
text
require() 调用
↓
路径解析
↓
缓存检查(require.cache)
↓
文件定位(.js/.json/.node)
↓
模块包装(function wrapper)
↓
模块执行(module.exports)
↓
结果返回
🧠 补充:模块缓存细节
-
所有加载过的模块都会被缓存(除非手动清理):
jsdelete require.cache[require.resolve('./someModule')];