You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js动态导入JSON文件缓存导致返回旧值无法更新问题

问题原因

加时间戳清缓存的写法不生效,核心是两个认知偏差:

  • 你参考的追加查询参数绕过缓存的方案,只对网络地址的ESM导入有效,本地文件模块根本不吃这一套。Node处理本地模块时,缓存键是文件的真实绝对路径,你直接在path拼接的字符串后面加?xxx=xxx,要么会被当成文件名的一部分去找不存在的文件,要么被加载器直接把查询串截掉,永远命中同一个缓存条目,当然拿不到新值。
  • path.join拼出来的是操作系统认的文件路径,不是ESM动态导入要求的file://协议URL,传非标准路径给import()本身就属于不规范用法,行为全靠加载器容错,出现缓存不刷新的问题完全符合预期。

说白了,import()天生是用来加载静态模块的,默认带永久缓存,从设计上就不适合读运行时会反复修改的文件。

解决方案

方案1:文件系统API直接读取(生产环境首选)

完全绕开ESM模块缓存逻辑,每次请求直接读取磁盘上的最新文件内容解析返回,行为100%可控,没有缓存、内存泄漏之类的幺蛾子。
改造步骤:

  1. 新增引入fs promise API:
import { readFile } from 'fs/promises';
  1. 替换原有的loadJSON函数:
const loadJSON = async () => {
  const filePath = path.join(__dirname, 'values.json');
  const fileContent = await readFile(filePath, 'utf-8');
  return JSON.parse(fileContent);
};

改完后不需要加任何特殊启动参数,只要values.json文件修改保存,下一次请求就能拿到最新内容。

方案2:构造合法file URL绕过缓存(仅适合低频调试场景)

如果一定要用动态import加载JSON,需要先把本地路径转为标准file://协议URL,再追加时间戳参数,让Node把带不同参数的地址识别为全新模块,绕过原有缓存。
注意:这个方案存在明确的内存泄漏问题——每次生成的带新时间戳的模块都会永久驻留在ESM缓存中无法被回收,接口QPS高的话服务内存会持续上涨,绝对不要在生产环境用。
改造步骤:

  1. 新增引入路径转URL的工具方法:
import { pathToFileURL } from 'url';
  1. 替换原有的loadJSON函数:
const loadJSON = async () => {
  const filePath = path.join(__dirname, 'values.json');
  const jsonUrl = pathToFileURL(filePath);
  jsonUrl.searchParams.set('update', Date.now());
  const values = await import(jsonUrl.href);
  return values.default;
};
补充说明

你启动服务时加的--experimental-json-modules参数在Node 18及以上版本已经不需要了,JSON模块导入已经成为稳定特性,但不管版本新旧,都不建议用动态import读取运行时会变更的JSON文件。


内容的提问来源于stack exchange,提问作者Eyal Solomon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:48:49