
Node.js 默认缓存 require() 加载的模块,导致后续读取 JSON 文件时始终返回首次加载的内容;本文详解如何通过清除模块缓存实现动态重载,并提供安全、可复用的实践方案。
node.js 默认缓存 `require()` 加载的模块,导致后续读取 json 文件时始终返回首次加载的内容;本文详解如何通过清除模块缓存实现动态重载,并提供安全、可复用的实践方案。
在 Node.js 中,require() 不仅用于加载 JavaScript 模块,也支持直接导入 JSON 文件(如 require('./config.json'))。但这一便利性背后隐藏着一个关键机制:所有通过 require() 加载的模块(包括 JSON)都会被缓存在 require.cache 对象中。这意味着,即使文件内容在运行时被修改(例如通过 fs.writeFileSync),下一次 require() 仍会从内存缓存中返回旧数据,而非重新读取磁盘文件。
上述问题在需要“热更新配置”或“状态持久化到 JSON”的场景中尤为常见——比如每次请求递增计数器并写回文件,却始终读到初始值。根本原因正是缓存未失效。
✅ 正确解法:手动清除模块缓存
要强制 Node.js 重新解析并加载最新 JSON 内容,需在 require() 前显式删除对应模块在 require.cache 中的条目。关键点在于:必须使用模块的绝对路径(即 require() 实际解析后的完整路径)作为缓存键,因为 require.cache 的键是规范化后的绝对路径,而非相对路径。
以下为修复后的完整示例:
const path = require('path');
const fs = require('fs').promises;
// 安全的 JSON 读取函数:自动清除缓存并重新加载
async function readJsonFresh(filePath) {
const absolutePath = path.resolve(filePath);
// 清除缓存(注意:必须用绝对路径)
delete require.cache[absolutePath];
// 同步 require —— 因为 JSON 是纯数据,无副作用,且需确保读取最新内容
return require(absolutePath);
}
app.use('/change', async (req, res) => {
try {
// 动态读取最新 JSON 内容(绕过缓存)
const data = await readJsonFresh('./number.json');
const num = data.number;
console.log('Current number:', num); // 正确输出 1 → 2 → 3...
// 修改后写回文件
await fs.writeFile(
path.join(__dirname, 'number.json'),
JSON.stringify({ number: num + 1 }, null, 2),
'utf8'
);
res.status(200).json({ success: true, next: num + 1 });
} catch (err) {
console.error('Failed to update JSON:', err);
res.status(500).json({ error: 'Internal server error' });
}
});⚠️ 重要注意事项
- 路径必须绝对化:require.cache 的键是 path.resolve() 后的绝对路径。若传入 './number.json',缓存键可能不匹配,导致清除失败。务必使用 path.resolve() 或 path.join(__dirname, ...)。
-
require() 是同步操作:虽然 JSON 读取本身轻量,但在高频请求中频繁 require() 可能成为瓶颈。生产环境建议改用 fs.readFile() + JSON.parse() 组合(完全绕过模块系统),更可控且避免缓存干扰:
const content = await fs.readFile('./number.json', 'utf8'); const data = JSON.parse(content); // 始终读取磁盘最新内容 - 缓存清除时机:必须在 require() 之前执行 delete require.cache[...];顺序颠倒将无效。
- 多进程/集群场景不适用:该方法仅作用于当前 Node.js 进程。若应用部署在 PM2 集群或多实例中,各进程缓存独立,需配合外部存储(如 Redis)实现跨进程状态同步。
✅ 总结
Node.js 的模块缓存机制提升了启动性能,但在需动态读取外部文件的场景下需主动管理。通过精准清除 require.cache 条目,可安全实现 JSON 模块的“按需重载”。对于简单原型或低频服务,delete require.cache + require() 是快捷方案;而对于生产级应用,推荐直接使用 fs.readFile() + JSON.parse(),语义清晰、无缓存副作用、易于测试与调试。










