require()卡住或报undefined是CommonJS循环引用导致的死锁:A require B、B又require A,但A的module.exports未初始化完,B拿到空对象;需通过console日志和require.cache分析加载顺序定位闭环。

require()卡住或报 undefined 时,先看模块加载顺序
这不是语法错误,而是 CommonJS 模块加载器在解析依赖链时陷入死锁:A require B,B 又 require A,但 A 的 module.exports 还没赋值完,B 拿到的是空对象或部分初始化的 exports。Node.js 不报循环引用警告,只静默返回当前已导出内容。
典型现象包括:TypeError: xxx is not a function、读取配置项得到 undefined、断点进不去、console.log 输出顺序混乱。
- 在每个疑似模块顶部加
console.log('loading', module.id),运行后观察是否出现重复路径(如./a.js → ./b.js → ./a.js) - 别信 VSCode 的“跳转到定义”——它只解析字符串字面量,不反映真实 require 时机
- 在 VSCode 开发者工具 Console 中执行
Object.keys(require.cache),手动检查哪些模块被提前缓存但内容为空
ESM 里不会出现“半初始化 exports”,但 import 链路闭环更难察觉
ESM 是静态声明 + 全量绑定,不存在 CommonJS 那种“边执行边导出”的中间态。但它会在解析阶段就报错,比如 Error [ERR_IMPORT_CYCLE] 或直接卡在 import 行不往下走。
问题在于:VSCode 调试器(尤其是旧版 pwa-node)可能绕过 ESM 解析逻辑,导致断点命中但实际模块未正确链接;而终端 node index.mjs 成功,F5 却失败,往往是因为调试协议未对齐 ESM loader 链路。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 确认
launch.json中"type"字段是"node",不是"pwa-node"(后者在 2026 年已逐步弃用 ESM 支持) - 确保 Node.js ≥ v18.19.0,且未手动添加
--loader等参数——VSCode 会自动注入适配 ESM 的调试参数 -
import循环不会静默失败,但错误堆栈常指向第一个import行,需顺着at ...往上翻几层,找真正形成闭环的两个文件
用 ESLint + madge 提前发现闭环,别等 runtime 报错
运行时报错已是结果,静态分析才能定位源头。ESM 和 CJS 的 import/require 都能被工具识别,关键是选对规则和参数。
eslint-plugin-import 的 import/no-cycle 规则可捕获大部分显式导入闭环,但对动态 require() 或拼接路径的场景无能为力;madge 则通过 AST 解析全量依赖图,适合排查跨多层、含条件加载的隐藏循环。
- 启用 ESLint 检测:
"import/no-cycle": ["error", { "maxDepth": 3 }],maxDepth设太大会误报,设太小会漏掉深层闭环 - 运行
npx madge --circular --extensions js,mjs,cjs src/,输出类似src/a.mjs → src/b.cjs → src/a.mjs就是混合模块循环的铁证 - VS Code 插件 “Dependency Analytics” 可在保存时实时标出循环链,点击直接跳转到问题
import或require行
修复时别删 require,要拆解加载期依赖
单纯删掉某处 require() 往往引发新错——因为逻辑耦合还在。必须把“加载时依赖”转为“运行时依赖”,核心就两条路:延迟加载,或提取共享状态。
ESM 场景下,await import('./utils.mjs') 是合法且推荐的跨类型调用方式;CJS 场景下,用 createRequire(import.meta.url) 构造的 require 仍只能加载 CJS 模块,不能解决 .mjs 加载问题。
- 工具类模块(logger、db client)适合延迟加载:把
require()移进函数体,调用时再加载,此时对方早已初始化完毕 - 配置、常量、基础数据应抽到独立
shared.cjs或constants.mjs,A 和 B 都引入它,彼此不再直接require/import对方 - 混合项目中,
.mjs文件不能被require()加载,哪怕你写了createRequire——这是 Node.js 解析器硬性限制,不是配置问题

















