RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-06-01中級

Metro・EASのビルドが『JavaScript heap out of memory』で落ちるときの対処

RorkやExpoのアプリをビルドしている途中で『FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory』が出て止まる——その原因と、ローカル・EAS両方での具体的な対処をまとめました。

Metro4EAS Build14メモリ3Expo149トラブルシューティング77

画像アセットの多い壁紙アプリをビルドしていたとき、進捗が9割近くまで進んだところで突然ターミナルが赤く染まりました。FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory。何度やり直しても同じ場所で落ちます。私はこの数年、6本の壁紙アプリを並行して運用していますが、アセット数が一定を超えたアプリだけがこの症状に当たりました。

このエラーは「コードが間違っている」のではなく「Node.js に割り当てられたメモリが足りていない」というサインです。原因がコード以外の場所にあるぶん、エラーメッセージだけ眺めても解決の糸口が見えにくいのが厄介なところです。ここでは、ローカルの Metro と EAS Build の両方で、どこに手を入れれば最短で復旧できるかを順を追って整理します。

まず症状と再現条件を切り分ける

このエラーが出る典型的な場面は3つあります。npx expo start でバンドル中に落ちる、eas build のクラウドビルドで Gradle/Xcode 前のバンドル生成段階で落ちる、expo export で本番バンドルを書き出すときに落ちる、です。

共通しているのは「JavaScript のモジュールを大量に同時展開する瞬間」だという点です。Node.js は既定でヒープ上限が決まっており(バージョンや環境によって概ね2GB〜4GB程度)、巨大なアプリや大量のアセットを抱えるとこの上限に先に到達します。つまり、アプリの規模が育った証拠でもあるわけです。

切り分けの第一歩として、本当にメモリ不足なのかを確認します。ビルドコマンドの前に上限を一時的に引き上げてみて、それで通るなら原因はほぼ確定です。

# 一時的にヒープ上限を8GBに引き上げて再現するか確認
NODE_OPTIONS=--max-old-space-size=8192 npx expo start --clear

これで落ちなくなったなら、メモリ不足が原因だと断定できます。逆にこれでも落ちる場合は、循環参照や無限ループなど別の問題を疑う必要があります。

対処1: ローカルのヒープ上限を恒久的に引き上げる

毎回環境変数を打つのは現実的ではないので、package.json のスクリプトに組み込みます。チームや別マシンでも同じ挙動になり、設定漏れを防げます。

{
  "scripts": {
    "start": "NODE_OPTIONS=--max-old-space-size=8192 expo start",
    "export": "NODE_OPTIONS=--max-old-space-size=8192 expo export"
  }
}

Windows では NODE_OPTIONS=... の前置きが効かないので、cross-env を挟むと OS をまたいで動きます。

{
  "scripts": {
    "start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 expo start"
  }
}

数値は搭載メモリの半分程度を目安にします。16GB のマシンなら8192(8GB)が安全圏で、これより大きくしても物理メモリを超えるとスワップが発生して逆に遅くなります。私は手元の Mac では8192で安定し、それ以上に上げても効果はありませんでした。

対処2: EAS Build はリソースクラスを上げる

ローカルではなくクラウドビルドで落ちる場合、NODE_OPTIONS をローカルで設定しても意味がありません。EAS Build のビルドマシン側のメモリを増やす必要があります。eas.json の各プロファイルに resourceClass を指定します。

{
  "build": {
    "production": {
      "android": { "resourceClass": "large" },
      "ios": { "resourceClass": "large" },
      "env": {
        "NODE_OPTIONS": "--max-old-space-size=8192"
      }
    }
  }
}

ここでのポイントは、resourceClass でマシン自体のメモリを増やしつつ、env で Node のヒープ上限も合わせて引き上げることです。マシンのメモリだけ増やしても、Node 側の上限が低いままだと結局同じ場所で落ちます。両方を揃えて初めて効きます。なお large は無料枠の対象外になることがあるため、料金プランは事前に確認しておくと安心です。

対処3: そもそもバンドルに載せる量を減らす

メモリを増やすのは対症療法です。アプリが育ち続ける前提なら、バンドルに載るモジュール量を構造的に減らしておくほうが長く効きます。metro.config.js でインライン展開を有効にすると、起動時に一度に読み込むモジュール数を抑えられます。

// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
 
const config = getDefaultConfig(__dirname);
 
config.transformer.getTransformOptions = async () => ({
  transform: {
    experimentalImportSupport: false,
    inlineRequires: true,
  },
});
 
module.exports = config;

画像アセットについても、巨大な PNG を JS バンドルに巻き込まないよう、require で参照する画像は最適化済みのものに差し替えておきます。私の壁紙アプリでは高解像度画像をリモート配信に切り出した結果、バンドル生成時のメモリ消費が目に見えて下がりました。アセットをローカルに抱え込みすぎないことが、長期的にはいちばん効く予防策だと感じています。

Android側のGradleで落ちる場合は別の上限を疑う

紛らわしいのですが、Androidビルドで似たメモリ不足が出ても、それがNode.jsではなくGradle(JVM)のヒープ不足であることがあります。ログに JavaScript heap ではなく Java heap spaceGC overhead limit exceeded と出ていたら、引き上げる場所が違います。この場合は android/gradle.properties のJVM引数を調整します。

# android/gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m

NODE_OPTIONS をいくら上げてもこちらは効きません。エラーメッセージの一語(JavaScript なのか Java なのか)で対処先が分かれる、という点だけ覚えておくと、無駄な試行錯誤を避けられます。私も最初の頃は両者を混同して、Node側ばかり触って時間を溶かしました。ログの主語を最初に読む癖をつけてから、復旧がぐっと速くなりました。

再発させないための習慣

このエラーは、アプリが順調に成長しているときほど不意に現れます。私は2014年から個人でアプリ開発を続け、累計5,000万ダウンロードに育つ過程で、機能やアセットが増えるたびに同じ壁にぶつかってきました。だからこそ、CI のビルドプロファイルには最初から NODE_OPTIONS を入れておき、アセット追加時はバンドルサイズの変化を確認する、という運用を習慣にしています。

次の一手としては、まず手元で NODE_OPTIONS=--max-old-space-size=8192 を付けて再現するかを確かめてください。そこで通るなら、上で紹介した恒久設定に落とし込むだけで、このエラーとはしばらく無縁でいられます。同じ場所で何度も止まって困っている方の、最短の復旧の助けになれば幸いです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-05-03
Rork で「Unable to resolve module」が出たときに最初に確認する5つのこと
Rork や React Native / Expo 開発でよく出る「Unable to resolve module」エラーの原因を5パターンに整理し、確認順序とコマンドつきで素早く解決する手順を紹介します。
開発ツール2026-04-25
Rork でアプリアイコンを変更したのに反映されない時の対処法
Rork でアプリアイコンを差し替えたのに古いアイコンが残る — iOS のアイコンキャッシュ、EAS Build のビルドキャッシュ、Android のアダプティブアイコン未設定など、原因別に確実な対処法をまとめました。
開発ツール2026-04-24
Metro bundlerが固まる・Fast Refreshが効かない時の診断手順
Rorkで生成したExpoアプリでMetro bundlerが固まる、Fast Refreshが反映されない——そんな時に順番にチェックすべき診断ステップと、安全なリセット手順をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →