launch.json 必须配置 env 并设置 "node_options": "--enable-source-maps --no-warnings",否则 inversifyjs 因缺少装饰器元数据支持而无法解析依赖;同时需配合 tsconfig.json 中启用 emitdecoratormetadata 和 experimentaldecorators,并正确配置 outfiles 与 sourcemap 路径。

launch.json 必须配 env 才能加载 InversifyJS 容器
InversifyJS 依赖 TypeScript 的装饰器(@injectable、@inject)和反射元数据,而 Node.js 默认不启用这些特性。调试时若容器报错 Cannot resolve 'xxx' at runtime 或 Reflect.getMetadata is not a function,根本原因是没开启 emitDecoratorMetadata 和 experimentalDecorators,且 Node 运行时缺少 NODE_OPTIONS 支持。
正确做法是在 launch.json 的配置中显式注入环境变量:
-
"env": { "NODE_OPTIONS": "--enable-source-maps --no-warnings" }—— 仅开启 source map 不够,必须加--enable-source-maps才能让断点映射到 TS 源码; - 若用
tsc编译输出到dist/,还需补上"outFiles": ["${workspaceFolder}/dist/**/*.js"],否则断点会失效; - 务必在
tsconfig.json中确认已启用:"emitDecoratorMetadata": true、"experimentalDecorators": true、"moduleResolution": "node"。
调试时容器 bind 失败?检查 kernel.bind 是否在 bootstrap 阶段执行
InversifyJS 的容器绑定(kernel.bind)必须在应用启动前完成,且不能延迟到异步回调里(比如 setTimeout 或 Promise.then 中)。VSCode 调试器暂停时若看到 kernel.getAll 返回空数组,大概率是绑定逻辑没被执行,或执行时机晚于实例解析。
常见错误场景:
- 把
bind写在某个模块的export语句后,但该模块未被任何地方import—— TypeScript 的 tree-shaking 或懒加载会让这部分代码根本不运行; - 使用
async/await初始化容器(如从 config 文件读取依赖列表再 bind),但调试器在container.get()前就暂停了,而 async 初始化还没结束; - 多个
Kernel实例混用:一个在inversify.config.ts创建,另一个在app.ts里 new 出来,导致 bind 和 get 不在同一个容器里。
断点进不到 @inject 构造函数?确认 skipFiles 没误杀 node_modules/inversify
VSCode 默认在 launch.json 中设了 "skipFiles": ["<node_internals>/**"]</node_internals>,这会跳过所有内置模块,但 InversifyJS 是第三方库,它的构造函数调用链(如 kernel.get → _get → _planAndResolve)如果被跳过,你就看不到依赖解析过程,也无法观察 bindingToApply 等关键变量。
临时调试建议:
- 删掉
skipFiles字段,或改为更精确的过滤:"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/(?!inversify).**"]</node_internals>; - 在
inversify.d.ts或node_modules/inversify/lib/kernel/kernel.js中手动加debugger;,再配合 F11 步入; - 避免在
@inject参数上直接设断点——TypeScript 编译后参数名会被擦除,断点实际落在生成的 JS 函数参数位置,容易偏移;改用在构造函数首行设断点更可靠。
attach 模式下无法解析 @inject?node --inspect 必须带 --enable-source-maps
用 nodemon 或 npm run dev 启动服务后附加调试(request: "attach"),常出现 @inject 参数为 undefined。这不是 InversifyJS 的 bug,而是 V8 Inspector 无法读取 TypeScript 编译后的装饰器元数据,因为源码映射缺失。
启动命令必须显式启用 source map 支持:
- 错误写法:
node --inspect dist/index.js—— 元数据丢失,Reflect为空; - 正确写法:
node --inspect --enable-source-maps dist/index.js; - 若用
nodemon,在launch.json中写:"runtimeExecutable": "nodemon", "runtimeArgs": ["--exec", "node", "--inspect", "--enable-source-maps", "${workspaceFolder}/dist/index.js"]。
真正麻烦的不是配置本身,而是每次修改 tsconfig.json 或切换构建工具(tsc / esbuild / swc)时,source map 输出路径、内联方式、元数据注入行为都会变 —— 这些细节不会报错,只会让断点静默失效或注入失败,得靠 console.log(Reflect.getMetadata('design:paramtypes', YourClass)) 实时验证。










