必须手动用 node --inspect=9229 app.js 启动再 vscode attach,才能捕获 require 阶段闭包、全局缓存等早期泄漏源;直接 launch 启动调试器介入太晚,无法记录模块加载期的根引用链,且 launch.json 必须设为 attach 模式并严格对齐端口与路径映射。

必须手动用 node --inspect=9229 app.js 启动,再让 VSCode attach,否则根本捕获不到 require 阶段的闭包泄漏和全局缓存误存——这是绝大多数人卡住的第一步。
为什么不能直接用 VSCode launch 启动调试
VSCode 的 launch 模式启动 Node 进程时,调试器介入太晚。require 阶段创建的模块缓存、顶层 Map 实例、未取消的 setInterval、EventEmitter.on 监听器,这些早期泄漏源在调试器连接前就已驻留堆中,快照里完全看不到它们的根引用链。
-
launch.json中"type": "pwa-node"+"program": "app.js"是“假调试”:进程生命周期不可控,GC 前后状态无法对齐 - 真实泄漏常发生在模块加载期,比如
const cache = new Map()写在文件顶层,key 是请求对象或临时Buffer - 用
nodemon时也得加--inspect参数,否则 Chrome DevTools 连不上,nodemon --inspect=9229 app.js
Chrome DevTools Memory 面板才是唯一可靠入口
VSCode 内置调试器不支持堆快照对比、Retained Size 排序、Detached 对象筛选等关键功能。所有分析必须进 chrome://inspect → Configure → 添加 localhost:9229 → 点 inspect → 切到 Memory 面板。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 至少拍 3 次快照:
snapshot-0(空载)、snapshot-1(触发一次接口/操作后)、snapshot-2(等待 30 秒 GC 后) - 右键任一快照 → Compare to previous snapshot,按
Retained Size降序排列 - 重点筛
Closure类型:展开看Retainers面板,若出现cache、handlers、pendingRequests或大Buffer,基本就是泄漏根因 -
Detached不是 DOM 专属:Node.js 里被闭包捕获又没释放的EventEmitter、Timeout、fs.readFileSync返回的Buffer,也会被标为 Detached
launch.json 必须配成 attach 模式
VSCode 要连上你手动启动的进程,launch.json 不能写 program,必须设为 attach 类型,并严格对齐端口与路径映射。
-
"type": "pwa-node"(新版 Debugger 插件要求) "request": "attach"-
"port": 9229(必须和命令行--inspect=9229一致) -
"localRoot": "${workspaceFolder}"和"remoteRoot": "${workspaceFolder}"都要填,否则快照里变量名全显示为<anonymous></anonymous> - 开发环境建议加
--max-old-space-size=1024启动,加速 OOM 触发,缩短定位周期
真正难的不是拍快照,而是识别哪些 Closure 是“该活”的、哪些是“不该活却赖着不走”的——这需要结合代码上下文判断引用链是否合理,比如一个 setTimeout 回调里捕获了整个 req 对象,但业务上它本该在响应结束后立刻释放,那就一定是泄漏点。










