vscode调试中await import()不命中断点,需在launch.json中启用sourcemaps、固定program路径、排除skipfiles干扰,并在await后设断点;createrequire加载的.cjs文件断点失效主因是路径映射或sourcemap缺失。

VSCode 调试时 await import('./utils.mjs') 不停断点怎么办
动态 import() 是 CommonJS 文件里安全加载 ESM 模块的唯一合法方式,但 VSCode 默认调试配置不会自动进入 import() 加载的目标模块——不是 bug,是默认行为。断点设在 utils.mjs 里,运行时直接跳过,根本不停。
- 必须在
launch.json中显式启用sourceMaps(即使你写的是纯 JS):ESM 模块路径解析依赖 Node 的内部映射机制,VSCode 需靠 source map 对齐原始行号 -
program字段不能用${file}动态值——它会绕过 Node 的 ESM 解析器,导致import()返回 Promise 后 resolve 的模块无法被调试器识别;应固定为入口文件路径,如"${workspaceFolder}/index.js" - 确保
utils.mjs所在目录没被skipFiles意外屏蔽(比如写了"/**"却没排除具体路径);推荐精确写法:"!/src/**"表示“除了 /src 下的都跳过”
createRequire(import.meta.url) 创建的 require 为什么设不了断点
createRequire 生成的 require 函数本质仍是 CommonJS 加载器,它只能加载 .cjs 或未声明 "type": "module" 的 .js 文件。你用它加载 config.cjs,VSCode 调试器能进,但前提是这个文件没被构建工具转成 dist/config.cjs 且没配对的 .map 文件——否则断点绑定失败,红点变空心。
- 检查
config.cjs是否在outFiles列表中(如果用了打包);若没打包,outFiles可删,但必须保留"sourceMaps": false(避免 VSCode 错误期待 map 文件) - 不要给
createRequire的结果重命名成require后再全局替换旧require——这会让调试器混淆模块上下文,断点位置错乱 - 该函数返回的
require无法加载.mjs,尝试会直接抛ERR_REQUIRE_ESM,和顶层require()行为一致
断点进了 node_modules 的 ESM 包(比如 glob@10),怎么快速跳出
第三方包升级为 ESM 后,其内部 export 语句会被 Node 当作模块边界处理,VSCode 单步 F11 时极易掉进 node_modules/glob/xxx.mjs,而你并不需要调试它。
- 立刻修改
.vscode/launch.json的skipFiles,加入"/node_modules/**"和"<code>**/node_modules/**"(双写确保匹配所有路径格式) - 别依赖
"/**"—— 它会跳过所有文件,包括你自己写的src/模块;必须用白名单式排除,例如:["/node_modules/**", "!/src/**"] - 改完
launch.json必须重启调试会话(Stop → F5),热重载不生效
为什么 import 语句本身能断住,但 import() 的回调里变量看不到
这是作用域隔离导致的:动态 import() 返回的模块对象在 Promise resolve 后才注入当前作用域,VSCode 的 Debug Console 在断点暂停时查不到尚未执行的 then() 或 await 后的变量。
- 不要在
.then()回调第一行设断点——那行代码还没执行,变量未声明;应在then()块内部、实际使用变量的地方设断点 - 用
async/await替代.then(),并在await import(...)下一行设断点,此时模块已加载,变量可查 - Debug Console 里输入
await import('./utils.mjs')是非法的——它不在当前 async 上下文中,会报SyntaxError: await is only valid in async function











