vscode调试next.js服务端代码必须用node --inspect启动并attach,因next.js 13+主进程不执行业务逻辑,真实代码运行在动态fork的子进程中,直接attach主进程导致断点无法绑定且提示“breakpoint ignored because generated code not found”。

VSCode 调试 Next.js 服务端代码(如 getServerSideProps、pages/api/)必须用 node --inspect 启动并 Attach,不能靠默认 launch 配置——否则断点永远不命中。
为什么 next dev 默认断点不生效
Next.js 13+(尤其是 App Router)启动后,主进程只是调度器,真正执行业务逻辑的是动态 fork 出的子进程(比如 RSC server、API handler)。VSCode 直接 attach 到主进程,根本找不到 getServerSideProps 的源码上下文。
典型现象:getServerSideProps 里打的断点显示为空心圆,hover 提示 “Breakpoint ignored because generated code not found”。
-
next dev本质是包装脚本,不是直接运行的 Node.js 入口,launch.json里设"program": "node_modules/next/dist/bin/next"没用 - source map 默认不生成或路径映射错位,尤其在 TSX 文件中,SWC 编译器默认不输出完整 sourcemap
- 热重载会 kill 旧进程、拉起新进程,没配
"restart": true就会断连
必须开启 experimental.sourceMaps 并加 --inspect
只改 launch.json 不行,两件事缺一不可:
- 在
next.config.js中显式启用 source map:experimental: { sourceMaps: true }(Next.js 13.4+);旧版需手动 patch Webpackdevtool: 'source-map' - 修改
package.json的dev脚本,加--inspect=9229:"dev": "next dev --inspect=9229" - 若端口被占,可换端口(如
--inspect=0.0.0.0:9230),但必须同步改launch.json的port
别用 --inspect-brk 做日常调试——它会让进程卡死在第一行,每次保存都得手动 resume,严重拖慢开发节奏。
launch.json 必须用 attach 模式且配对 localRoot/remoteRoot
配置类型必须是 "type": "node" + "request": "attach",不是 launch 或 pwa-node。
关键字段不能省:
-
"port": 9229(和--inspect端口一致) -
"restart": true(热重载后自动重连) -
"localRoot": "${workspaceFolder}"和"remoteRoot": "${workspaceFolder}"必须完全一致——Next.js 的 sourcemap 是相对路径生成的,不配这个,断点就映射不到源文件 -
"sourceMaps": true(显式打开,别依赖默认)
如果用 pnpm,注意 node_modules/next/dist/bin/next 实际路径可能是 node_modules/.pnpm/next@*/node_modules/next/dist/bin/next,但 attach 模式下不用写它——你 attach 的是已启动的进程,不是去 run 它。
调试 API Route 或 Server Actions 时容易忽略的点
很多人测 API Route 时断点跳过,其实只是请求没发到本地服务:
- 用
curl http://localhost:3000/api/hello测试最可靠,排除浏览器插件、缓存、跨域拦截干扰 - 确认环境变量:
process.env.NODE_ENV === 'development',但某些逻辑可能因if (process.env.NODE_ENV === 'production')被跳过 - Server Actions 的断点要打在 action 函数体内,不是组件渲染函数里;App Router 下它默认跑在服务端,不能指望 Chrome DevTools 捕获
- 客户端逻辑(如
useEffect)必须放在"use client"组件内,否则仍走 SSR,VSCode 断点无效
复杂点在于:Next.js 的进程模型是动态的,source map 生成路径又依赖构建时的 cwd 和配置顺序——哪怕只漏掉 experimental.sourceMaps 或 remoteRoot,断点就成摆设。动手前先跑一遍 curl 确认服务真在跑,再看终端有没有 Debugger listening on ws://... 日志,比反复重启 VSCode 更省时间。











