← 中文资源

简体中文版本

Webpack 构建堆内存溢出 — 生产构建 OOM 修复

测量 webpack 构建内存与 stats,提高 Node 堆上限,关闭或外置 source map、拆分 chunk,并清理重复依赖以解决构建 OOM。

阅读英文原文

现象

构建报 FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory;本地能过而 CI 因内存较小失败;压缩阶段内存持续攀升不释放;新增大依赖后构建时间和内存一起上涨。

诊断

先用显式堆上限复现:

NODE_OPTIONS=--max-old-space-size=4096 npx webpack --mode production
node -e "console.log(require('v8').getHeapStatistics().heap_size_limit/1024/1024 + ' MB')"

4 GB 能构建成功,说明默认堆就是直接限制;仍然 OOM 则要查模块图或插件。抓取构建统计找出最大的模块:

npx webpack --mode production --profile --json > stats.json
node -e "const s=require('./stats.json'); console.log(s.modules.sort((a,b)=>b.size-a.size).slice(0,10).map(m=>[m.name,m.size]))"

同一依赖出现多份副本,通常是解析或链接问题,而不是堆太小。再用 --no-devtool 对比,若关闭 source map 后通过,说明生成的大型字符串才是内存放大器。

修复

生产构建关闭或外置 source map,设置实测所需的堆上限,启用文件缓存并拆分入口:

module.exports = {
  mode: 'production',
  devtool: false,
  cache: { type: 'filesystem' },
  optimization: { splitChunks: { chunks: 'all' } },
};

同时删除重复依赖、对低频路由使用动态 import、升级 webpack 与 loader;CI 容器内存应按实测峰值配置,而不是只调大 NODE_OPTIONS。盲目加堆可能让操作系统 OOM killer 直接杀掉进程,反而更难定位。

验证

清理缓存后按新配置重新构建,确认在设定堆内完成并记录 CI 峰值内存;对比产物体积,启动应用验证页面正常。若启用外置 source map,还要确认浏览器能解析到原始源码,而不是只生成文件。