VSCode调试Next.js服务端代码断点不命中,根本原因是未连接到动态fork的子进程且未启用source map:需用--inspect启动并配置attach模式,同时在next.config.js中开启experimental.sourceMaps。

VSCode 调试 Next.js 服务端代码(getServerSideProps、app/api/xxx/route.ts、Server Actions)断点不命中,基本就是没连对进程 + 没开 source map —— 其他配置都是围绕这两点打补丁。
为什么 next dev 默认断点全灰?
Next.js 13+(尤其 App Router)启动后,主进程只是调度器,真正执行服务端逻辑的是动态 fork 出的子进程:getServerSideProps、API Routes、Server Actions 都跑在这些 worker 进程里。VSCode 默认 attach 到主进程,根本看不到这些函数的源码上下文。
典型现象:getServerSideProps 里打的断点显示为空心圆,hover 提示 "Breakpoint ignored because generated code not found"。
- 不是 launch.json 写错了,是根本没连到运行业务代码的那个 Node.js 进程
-
next dev本质是包装脚本,不是可直接调试的 Node 入口;设"program": "node_modules/next/dist/bin/next"在 launch 模式下也无效 - 热重载会 kill 旧子进程、拉起新子进程,没配自动重连就会断连
必须用 --inspect 启动 + attach 模式
让 Next.js 自己暴露 inspector 端口,VSCode 主动连接——这是唯一稳定路径。
- 改
package.json的dev脚本:"dev": "next dev --inspect=9229"(端口可换,但要和 launch.json 对齐) - 别用
--inspect-brk日常调试:它会让每次保存都卡在第一行,必须手动 resume,严重拖慢开发节奏 - 如果端口被占(比如 Chrome 占了 9229),换成
--inspect=0.0.0.0:9230,Docker / WSL 下 address 也得设成"0.0.0.0" - 启动顺序固定:先
npm run dev(或 pnpm/run),等终端输出ready - started server on http://localhost:3000后,再在 VSCode 里点 ▶️ 运行 attach 配置
launch.json 关键字段不能漏
必须是 "type": "node" + "request": "attach",不是 pwa-node,也不是 launch。
-
"port": 9229:必须和--inspect后端口一致 -
"restart": true:热重载后自动重连新子进程,否则断点秒失效 -
"skipFiles": ["<node_internals>/**"]:避免断点误停在 Node 内部代码里 -
"outFiles": ["${workspaceFolder}/.next/server/**/*.js"]:帮调试器定位编译后的服务端 JS 文件 -
"localRoot"和"remoteRoot"必须都设为"${workspaceFolder}":Next.js 的 sourcemap 是相对路径生成的,不配就映射不到源文件
sourceMaps 不开,断点永远找不到源码
Next.js 默认不把 source map 写入磁盘,尤其 App Router 下 SWC 编译器默认禁用。VSCode 连上了端口,也只能看到压缩后的 JS,无法映射回 .ts 或 .tsx。
- Next.js 13.4+:在
next.config.js加experimental: { sourceMaps: true } - 确认生成物存在:
.next/server/pages/xxx.js.map和.next/server/app/xxx/page.js.map应该有实际文件 - 验证是否真走 SSR:在
getServerSideProps或app/api/hello/route.ts里加console.log('pid:', process.pid),刷新页面看终端是否输出——没输出 = 压根没进服务端逻辑 - 浏览器直接访问
http://localhost:3000/api/hello,而不是点前端按钮跳转,避免客户端导航绕过 SSR
最容易被忽略的是 restart: true 和 localRoot/remoteRoot 的严格一致:热重载后进程 PID 变了,没 restart 就断连;路径映射错一位,断点就永远“unbound”。这两项一漏,前面所有配置都白搭。


















