元数据
| id | node-heap-oom | 收录 | 2026-08-29 |
|---|---|---|---|
| 问题域 | 编码代理与终端 | 主题分组 | 构建与部署 |
| 适用工具 | node · 外部工具npm · 外部工具 | ||
症状
前端项目打包/构建(webpack、vite、vue-tsc、jest 等)中途崩溃,控制台最后几行是:
```
<--- Last few GCs --->
.... MB: Mark-Compact ... allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
```
旧版 Node 上同一错误常写作 `FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory`。特征:项目越大越容易触发(依赖多/单文件大/tsc 全量类型检查);重试可能偶发通过;发生在 `npm run build` / `vue-tsc` / CI 打包阶段。
原因
Node 的 V8 引擎给 JS 堆设了默认上限,超过后 GC 也回收不动就放弃治疗直接崩。**默认上限不是固定的 2G**:现代 Node(64 位)默认约 4GB(本机 Node 22 实测 heap_size_limit = 4144MB),老版本或 32 位下更小(1.5~2G)——网上大量教程说的「默认 2G」是旧版本事实。构建工具要把整个依赖图 + 编译产物放内存,项目一大就顶到上限。
解法
按推荐顺序选:
1. **临时提上限(最快)**,三种写法等效:
- 命令行:`node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build`(或 `webpack`/`vue-tsc` 同理);
- 环境变量(CI/Jenkins/Windows 通用):`NODE_OPTIONS=--max-old-space-size=8192`,Windows 永久设置用 `setx NODE_OPTIONS=--max-old-space-size=8192`(注意 setx 永久、新开窗口生效);
- 写进 package.json:`"build": "node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build"`;Windows 下注意引号问题可用 `cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build`。
值按机器内存定(如 4096/8192),别超过物理内存太多,否则变 swap 卡死。
2. **长期优化(治本)**:构建缓存(webpack `cache` / vite 缓存)、代码分割/按需加载、升级构建工具(webpack→vite)、`vue-tsc --noEmit` 拆到单独阶段、依赖精简。内存压力来自「同时放内存的东西太多」,提上限只是把线抬高。
3. **区分系统 OOM**:若错误是 `Killed` 或 `Exit status 137`(容器/CI 里),那是操作系统杀的(cgroup/容器内存上限),调 `--max-old-space-size` 没用,要加容器内存或减并发。
验证证据
- 本地实测(2026-08-29,WSL Ubuntu,Node v22.22.1):
- 默认 heap_size_limit 实测 4144MB(`v8.getHeapStatistics`),证明「默认 2G」说法对现代 Node 已过时;`--max-old-space-size=8192` 后为 8240MB;
- 构造逐步分配大数组的脚本,默认上限运行 → 完整复现 `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`(含 Last few GCs / JS stacktrace / Native stack trace),进程 SIGABRT 退出码 134;
- `node --max-old-space-size=8192 <脚本>` → 分配至 6000MB 上限成功退出(退出码 0);
- `NODE_OPTIONS=--max-old-space-size=8192 node <脚本>` → 同样成功(退出码 0),证明环境变量写法与 CLI 等效;
- 文章里的 package.json 改法(node 直调 vite.js)属于 CLI 写法变体,同源已验证。
- 实测复现日志(2026-08-29)
来源与证据
素材来源:https://www.cnblogs.com/c2g5201314/p/19070905
验证证据:Evidence details kept locally (2026-08-29)