返回博客

Next.js dev 日志无上限膨胀吃满磁盘,SSR 输出残缺伪装成你的 bug

调试某个营销落地页,三个路由都返回 200,但 curl 拿回的 HTML 里整块 client island 区域凭空消失。TypeScript 零报错,SSR 日志也干净,怀疑自己刚抽的组件有问题,反复回滚还是复现。直到 Bash 工具执行一个写临时文件的命令时报了 ENOSPC: no space left on device——才意识到根本不是代码问题。

现象

  • curl http://localhost:3000/some-page 返回 200,但 HTML 缺少整段内容(<section> 级别的大块消失)。
  • 页面在浏览器里有时正常、有时只渲染骨架,像随机失败。
  • 没有任何 TypeScript / lint / build 错误。
  • Bash 执行写文件操作突然报 ENOSPC: no space left on device
  • du -sh .next 显示几十 GB。

根因

Next.js dev server(尤其是开了 Turbopack 的 13–16 版本)会把运行时错误写到:

.next/dev/logs/next-development.log

问题在于:这个日志没有任何 rotation 或大小上限。如果某个页面(哪怕是你完全没在改的页面)在每次请求或 Fast Refresh 时抛出运行时错误,它就会把完整的 stack trace 一遍遍追加进去。长跑一个 dev session 后,日志可以轻松涨到 20 GB 以上。

磁盘 100% 之后,Turbopack 写不了 build chunk,SSR 输出被强制截断——表现完全像你正在调试的那个页面出了 bug,但你的代码从头到尾都是对的。

坑:磁盘满导致的 SSR 截断,症状与代码 bug 完全相同

运行时错误来自另一个页面,而表现为你当前调试的页面 HTML 不完整。两者之间没有任何直接的报错关联,非常容易花大量时间在无辜的代码上排查。

排查步骤

先花 10 秒排除磁盘因素,再花时间看代码:

# 第一步:看磁盘是否满了
df -h /
 
# 第二步:看 .next 目录有多大
du -sh .next
 
# 第三步:找到元凶日志
du -sh .next/dev/logs/*

如果 df 显示接近 100%,而 .next/dev/logs/next-development.log 动辄十几 GB,基本确诊。

正解

不要 rm -rf .next(dev server 还在跑,会破坏它)。用 shell 截断操作立刻释放空间,同时不影响进程文件句柄:

# 截断日志,立即释放磁盘(dev server 不需要重启)
: > .next/dev/logs/next-development.log

截断后再验:

df -h /          # 空间应该跳回来
curl http://localhost:3000/some-page  # HTML 应该完整了

然后去找真正的噪音来源——在 .next/dev/logs/next-development.log 里搜重复出现的 stack trace,定位是哪个页面/组件在每次请求时抛错,把那个真正的 bug 修掉,否则日志会继续重新积累。

正解:截断日志 + 修真正的循环抛错

: > .next/dev/logs/next-development.log 是最安全的释放方式,不重启 dev server 也立即生效。之后务必追查日志里重复的 stack trace,修掉循环抛错的根因,否则下次 long session 会再次触发。

额外提示:MSW / provider 返回 null 是另一个原因

如果磁盘没满但 SSR HTML 也"看起来空",检查是否有 MSW mock provider 在 hydration 前返回 null,导致 client island 首屏为空。先用 df -h 排除磁盘,再用真实浏览器(非 curl)排除 hydration 问题——两者是不同的根因。

一句话外卖

Next.js dev 的运行时错误日志没有 rotation,一个无关页面的循环抛错就能把磁盘塞满,让你正在调试的页面 SSR 截断——遇到"代码没问题但输出残缺"先跑 df -h,10 秒排除磁盘因素,省去几小时冤枉排查。