You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行npm run build报JavaScript heap out of memory错误如何解决

问题根因

你的报错是新生代半空间分配失败(Committing semi space failed),不是老生代内存不足,所以之前只调整--max-old-space-size参数无效,核心问题出在代码逻辑上:

  • 无控制的异步并发:drawLayer是异步函数,你在循环中直接批量调用没有做等待,瞬间会创建成千上万的异步图片加载、文件写入任务,大量临时对象瞬间塞满新生代内存
  • 全局资源未释放:全局唯一的canvas实例绘制后未主动清理,加载的图片资源也没有解除引用,内存持续累积
  • 元数据全量内存驻留:所有生成的NFT元数据全部存在内存中直到最后一次性写入,生成量大时会占用极高内存
修复方案

1. 修改异步执行逻辑,控制并发

将createFiles改为异步函数,串行执行绘制任务,避免瞬间并发过高,同时新增元数据分批写入逻辑,减少内存占用:

const createFiles = async (edition) => {
  const layers = layersSetup(layersOrder);
  const tempMetaPath = `${buildDir}/${metDataFile}.tmp`;
  // 先写json数组开头
  fs.writeFileSync(tempMetaPath, '[');

  for (let i = 1; i <= edition; i++) {
    // 等待每层绘制完成再进入下一层
    for (const layer of layers) {
      await drawLayer(layer, i);
    }
    addMetadata(i);
    console.log("Creating edition " + i);

    // 每1000条元数据写入一次磁盘,清空内存
    if (i % 1000 === 0) {
      const suffix = i === edition ? '\n' : ',\n';
      fs.appendFileSync(tempMetaPath, JSON.stringify(metadata.splice(0, 1000)).slice(1, -1) + suffix);
    }
  }

  // 写入剩余的元数据和json数组结尾
  if (metadata.length) {
    fs.appendFileSync(tempMetaPath, JSON.stringify(metadata).slice(1, -1) + '\n]');
  } else {
    fs.appendFileSync(tempMetaPath, ']');
  }
  // 替换为最终的metadata文件
  fs.renameSync(tempMetaPath, `${buildDir}/${metDataFile}`);
  // 原来的createMetaData函数可以废弃不用
};

2. 新增资源释放逻辑

修改drawLayer函数,用完的资源主动解除引用,清理画布:

const drawLayer = async (_layer, _edition) => {
  let element = _layer.elements[Math.floor(Math.random() * _layer.elements.length)];
  addAttributes(element, _layer);
  console.log(_layer.location,element.fileName)
  const image = await loadImage(`${_layer.location}${element.fileName}`);

  ctx.drawImage(
    image,
    _layer.position.x,
    _layer.position.y,
    _layer.size.width,
    _layer.size.height
  );
  saveLayer(canvas, _edition);
  
  // 新增:释放资源
  image.src = '';
  ctx.clearRect(0, 0, canvas.width, canvas.height);
};

3. 调整Node启动参数

修改package.json中的build命令,同时调整新生代和老生代内存上限:

{
  "scripts": {
    "build": "node --max-old-space-size=16384 --max-semi-space-size=1024 你的构建入口文件路径.js"
  }
}

Windows系统如果直接在终端执行命令,需要注意参数直接跟在node后面,不要放在命令末尾。

内容的提问来源于stack exchange,提问作者mrhexxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:45:02