Vercel 上的内存失败要先分清两类:一种是 Node 自己报 JavaScript heap out of memory,另一种是 build container 被系统结束。前者可以调 V8 heap;后者通常要减少构建范围、清理缓存、拆依赖,或者找更高资源的 build 机器。
本文按 2026-05-24 重新比对 Vercel 和 Node.js 官方文档。最重要的变化是:不要再把 Hobby 简化成「1GB 内存不够」。当前公开文档写的是 Hobby / Pro build memory 都是 8192 MB,Pro 的直接差异在 CPU 和并发等资源,Enterprise 才是 custom 限制。
确认是不是内存问题?
Build Logs 里先搜这几个字符串:
| 日志片段 | 更像哪类问题 | 第一动作 |
|---|---|---|
JavaScript heap out of memory | V8 old space 到顶 | 调 NODE_OPTIONS,再看 Next.js / Webpack 阶段 |
Reached heap limit Allocation failed | Node heap 到顶 | 降低并行、减少 bundle、设 heap 上限 |
Killed / exit code 137 | 容器层资源被打爆 | 缩构建范围、清缓存、查 native 依赖 |
Build exceeded maximum duration | 时间限制,不是纯内存 | 看 45 分钟 build time 和生成文件数量 |
如果日志只停在 Creating an optimized production build,不要直接下结论。Next.js 这一段会同时跑编译、类型检查、静态生成和函数打包,内存峰值可能来自其中任一环。
Hobby / Pro / Enterprise 的限制在哪里?
按 Vercel Limits 当前表格,build container 的公开限制是:
| Plan | Build memory | CPU | 该怎么理解 |
|---|---|---|---|
| Hobby | 8192 MB | 2 | 单应用和小型 monorepo,从构建范围排查 |
| Pro | 8192 MB | 4 | CPU、并发和团队能力更好,但不是公开内存翻倍 |
| Enterprise | Custom | Custom | 资源、并发、支持和安全要求可以谈定制 |
所以这篇的判断规则很简单:Hobby 上 OOM,不要第一步就归因到套餐;Pro 上 OOM,也不要以为只能继续加钱,把 Node 版本、缓存键、Root Directory、buildCommand 和依赖图对齐,再决定是否找 Vercel Support 看 Enterprise 或特殊 build 资源。
还有两个容易混淆的数字:Vercel build time 是 45 分钟,Build cache 单个 cache key 最大 1GB 并保留一个月。缓存不等于内存,它只影响恢复依赖和框架缓存的速度;坏缓存会放大排查难度,但不会把 8GB 变成 16GB。
最短处理路径怎么排?
按这个顺序做,每次只改一个变量:
- 在 Build Command 前临时加
node -v && npm -v,确认 Vercel 实际 Node 版本。 - 固定 Node 版本,优先在 Project Settings 选 20.x / 22.x / 24.x,或者在
package.json写engines.node。 - 设置
NODE_OPTIONS=--max-old-space-size=6144,只针对 Node heap 到顶的日志。 - 用无缓存 redeploy 跑一次,排除旧
.next/cache、node_modules、Turborepo / Nx cache 的干扰。 - 检查 Root Directory 和 buildCommand,只构建当前 app 及其真实依赖。
- 再看 Next.js 配置、source map、静态生成页面数、图片和大依赖。
这套顺序的好处是成本低。Node 版本和缓存键是 Vercel 官方机制,monorepo 范围是最常见的人为配置问题,最后才轮到拆代码和换资源。
Node 版本和 NODE_OPTIONS 怎么设?
Vercel 当前可选 Node.js major version 是 24.x、22.x、20.x,新项目默认使用 Vercel 上最新的 LTS。项目后台路径是:
Project Settings -> Build and Deployment -> Node.js Version
如果团队希望版本跟代码走,可以在 package.json 固定:
{
"engines": {
"node": "22.x"
}
}
Node.js 官方文档里,--max-old-space-size=SIZE 的单位是 MiB,控制的是 V8 old memory section。内存接近上限时,V8 会花更多时间做垃圾回收;如果设置过高,容器里的 native module、压缩器、图片处理和系统进程就没有余量。
8GB build container 建议先这样试:
NODE_OPTIONS=--max-old-space-size=6144
如果日志仍是 heap limit,可以再试 6656。不要直接设 8192;那只是 build container 总量,不是 Node 进程可独占的 JavaScript heap。
缓存什么时候该清?
Vercel 会按 Framework Preset 缓存文件。Next.js 项目除了 node_modules/**,还会缓存 .next/cache/**。Build cache key 会受 Personal Account / Team、Project、Framework Preset、Root Directory、Node.js Version、Package Manager、Git branch 影响。
这些场景建议跑一次无缓存构建:
| 场景 | 为什么会干扰判断 | 操作 |
|---|---|---|
| Node 20 切到 22 / 24 | cache key 变化,首轮结果不代表稳定状态 | 先记录版本,再跑一次干净 build |
| Next.js / React 大版本升级 | .next/cache 可能混入旧编译结果 | Redeploy 时取消 Use existing Build Cache |
| lockfile 大改 | 依赖树和 native 包都变了 | 用 vercel --force 或设 VERCEL_FORCE_NO_BUILD_CACHE=1 |
| Turborepo / Nx 远端缓存异常 | 命中旧产物会掩盖真实构建范围 | 临时设 TURBO_FORCE=true |
清缓存不是长期修复。干净 build 能过、带缓存失败,重点查框架缓存和 remote cache;干净 build 也失败,回到内存峰值和构建范围。
Monorepo 从哪里缩小范围?
Vercel monorepo 的第一处开关是 Root Directory。一个仓库里有 apps/web、apps/admin、packages/ui 时,web 项目的 Root Directory 不该指向仓库根目录,除非 buildCommand 明确只构建 web。
第二处是 workspace 依赖声明。Vercel 跳过未受影响项目时,会看项目源码、内部依赖和 lockfile 影响范围;npm / yarn / pnpm / Bun workspace 要写完整,每个 package 的 name 要唯一,内部依赖也要在 package.json 里显式声明。
第三处是 buildCommand。Turborepo 可以写成:
{
"buildCommand": "turbo build --filter=web..."
}
Nx 项目则看目标名和 project graph,常见方向是只跑当前 app:
nx build web
如果 Build Logs 里出现了 docs、storybook、e2e、admin、marketing 同时构建,先别调 heap。那不是 Vercel 内存太小,而是部署项目把整个工作区都拉进了 build。
还没恢复时,单独查 Vercel 部署 失败
把不可确认限制写在排查记录里:本次是否只测了 Production、是否测过 Preview branch、Node 版本是否固定、无缓存 build 是否跑过、Root Directory 是否截图确认、Vercel 是否显示自定义 build 资源。
如果团队在跨地区协作时经常等 Vercel Dashboard 的 Build Logs 或 GitHub Checks 刷新,排查过程会被中断。可以把 GitHub、Vercel、Cloudflare 这些后台放在同一套工作环境里,用海外服务跑 GitHub Actions / Cloudflare 的稳定线路承载部署和日志查看,不要把网络抖动误判成平台构建失败。
代码层面还可以继续做四件事:
- 关闭或延后 production source map 上传,避免 build 阶段同时生成和上传大文件。
- 减少
getStaticPaths/ 静态生成页面数量,把长尾页改成 ISR 或运行时生成。 - 查大依赖是否进了 client bundle,例如全量 locale、PDF、Playwright / Puppeteer。
- 把图片压缩、schema 生成、搜索索引生成从 Vercel build 拆到独立 CI job。
这些都做完还稳定失败,再带着 deployment URL、失败日志、Node 版本、无缓存结果、Root Directory 截图找 Vercel Support。Enterprise 的资源是 custom,不要在文章或团队 runbook 里写死某个内存数字。