模块加载机制是 Node.js 遵循 CommonJS 规范 实现的核心规则,定义了使用 require() 导入模块时,系统识别、查找、加载、执行模块的完整流程。 Node.js 会按照缓存优先、优先级分级、逐级向上查找的逻辑加载模块,同时自带缓存机制避免重复执行,极大提升了程序运行效率,保障了模块化开发的稳定性。
Node.js 对已加载的模块会进行永久缓存,这是模块加载的第一优先级规则。 无论使用 require() 加载多少次同一个模块,模块代码只会执行一次,后续加载直接读取缓存结果,不会重复执行模块代码。
缓存范围:内置模块、自定义模块、第三方模块全部支持缓存
缓存标识:以模块的绝对路径作为唯一缓存 key
优势:避免重复执行代码,提升加载效率,节约系统资源
// 第一次加载:执行模块代码,并存入缓存
require('./test.js');
// 第二次加载:直接读取缓存,模块内部代码不会再次执行
require('./test.js');内置模块是 Node.js 官方提供的核心模块(如 fs、path、http),加载优先级仅次于缓存,是所有模块中优先级最高的业务模块。
加载标识符直接写模块名:require('fs')
优先级最高:即使 node_modules 中存在同名第三方包,也会优先加载官方内置模块
无需安装、无需配置路径,直接加载
// 永远加载 Node.js 内置 fs 模块
const fs = require('fs');
const path = require('path');自定义模块是开发者编写的 .js/.json/.node 文件,必须使用相对路径标识(./ 或 ../ 开头)。
路径必填:不写 .//../,Node.js 会误识别为内置模块或第三方模块
扩展名可省略:Node.js 会自动按顺序补全扩展名尝试加载
补全顺序:精确文件名 → .js → .json → .node → 抛出错误
// 完整写法(推荐)
const utils = require('./utils.js');
// 省略扩展名:自动补全尝试加载
const utils = require('./utils');// 错误写法:缺少相对路径标识符,加载失败
const utils = require('utils');第三方模块(npm 安装的包)既不是内置模块,也不以相对路径开头,Node.js 会按照逐级向上查找 node_modules 的规则加载。
从当前文件所在目录的 node_modules 中查找
未找到,则进入父级目录的 node_modules 查找
重复向上遍历,直到文件系统根目录
全部查找失败,抛出 Cannot find module 错误
当前文件路径:C:/project/src/index.js 加载模块:require('moment') 查找顺序:
C:/project/src/node_modules/moment
C:/project/node_modules/moment
C:/node_modules/moment
查找失败,报错
// 加载第三方包,无需路径,直接写包名
const moment = require('moment');
const _ = require('lodash');Node.js 支持直接将一个目录当作模块加载,无需指定具体文件,系统会按照固定规则查找入口文件。
读取目录下的 package.json 文件,查找 main 字段指定的入口文件
若无 package.json 或 main 字段无效,自动尝试加载目录下的 index.js
以上两步均失败,抛出模块找不到错误
myModule/
├── index.js
└── package.jsonpackage.json 配置:
{
"name": "my-module",
"version": "1.0.0",
"main": "./index.js"
}// 直接加载目录,自动匹配入口文件
const myModule = require('./myModule');缓存模块(最高优先级)
内置模块
自定义模块
第三方模块(逐级向上查找)
目录模块(按规则匹配入口文件)
加载自定义模块时省略 ./,导致加载失败
认为多次 require() 会重复执行模块代码
目录模块缺少 index.js 和 package.json,导致加载报错
缓存机制:避免重复执行,提升性能
优先级机制:保障内置模块的安全性
自动补全:简化模块导入写法
目录模块化:支持封装复杂功能模块
缓存优先:模块首次加载后会被缓存,多次导入不重复执行
优先级:缓存 > 内置模块 > 自定义模块 > 第三方模块
自定义模块:必须用 .//../ 开头,扩展名可自动补全
第三方模块:从当前目录逐级向上查找 node_modules
目录模块:优先读取 package.json 的 main 字段,其次加载 index.js