GitHub Actions で Next.js のビルドが遅い・メモリ不足で落ちる:キャッシュ、メモリ、ランナーの大きさ
GitHub Actions の Next.js のビルドは、遅い理由とメモリ不足で落ちる理由が別々です。遅いのは、.next/cache が次の実行に渡っていないからです。Next.js はこのキャッシュをビルドからビルドへ使い回しますが、GitHub ホストランナーのジョブは新しい VM で始まるので、キャッシュのステップがなければ毎回まっさらなビルドになります(ログに No Cache Detected と出ます)。落ちるのは、プライベートリポジトリの ubuntu-latest が 8 GB で、大きなアプリの webpack のコンパイル、型チェック、ソースマップがそれを超えるからです。1 つ目は .next/cache への actions/cache で直します。2 つ目は、まず Next.js のメモリの設定(experimental.webpackMemoryOptimizations、本番のソースマップを切る)、それでも足りなければメモリの多いマシン、16 GB か 32 GB です。
Skipbox なら、そのメモリが定額です。runs-on: skipbox-8x16 で 16 GB・8 vCPU が月 12,000 円、skipbox-16x32 で 32 GB・16 vCPU が月 23,000 円。専用のマシンなので、パッケージのキャッシュはディスクに残り、actions/cache が保存したものは手元から読みます。実行時間は無制限です。
遅い:.next/cache が空から始まる
Next.js の CI でのビルドのキャッシュのガイドによれば、Next.js は「ビルドどうしで共有するキャッシュを .next/cache に保存」し、CI がこれをビルドの間で残さないと No Cache Detected のエラーが出ます。GitHub Actions のステップはこうです。
- uses: actions/cache@v4
with:
path: |
~/.npm
${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
キーはソースが変わるたびに変わるので、実行のたびに新しいキャッシュを保存し、GitHub のリポジトリごと 10 GB の枠を使います。Turborepo なら、Turborepo の GitHub Actions のガイドと同じく、タスクの outputs から .next/cache を外します("!.next/cache/**")。
メモリ不足:2 つの別のエラー
| ログに出るもの | 尽きたもの | すること |
|---|---|---|
JavaScript heap out of memory | Node 自身のヒープの上限。マシンのメモリはまだある | 上限を上げる:NODE_OPTIONS=--max-old-space-size=6144。マシンのメモリより小さく |
Process completed with exit code 137 | マシンのメモリ。Linux がプロセスを止めた | メモリを減らすか、メモリの多いマシンにする |
ヒープの上限をマシンのメモリより上げると、1 つ目のエラーが 2 つ目に変わるだけです。
メモリを減らす:Next.js の設定
Next.js のメモリの使い方のガイドから。
experimental.webpackMemoryOptimizations: true(v15.0.0 から)。コンパイルが少し長くなるかわりに、webpack のメモリのピークを下げます。- webpack のビルドワーカー。 コンパイルを別の Node のワーカーで動かし、メモリを減らします。v14.1.0 からは、独自の webpack の設定がなければ既定で有効です。設定があるなら
experimental.webpackBuildWorker: true。 - ソースマップを切る:
productionBrowserSourceMaps: falseとexperimental.serverSourceMaps: false。「Generating static pages」で落ちるならenablePrerenderSourceMaps: falseも。 - 測る:
next build --experimental-debug-memory-usage(v14.2.0 から)で、ビルド中のヒープの使用量が出て、上限が近づくとヒープのスナップショットも取れます。 - 型チェック:
typescript.ignoreBuildErrors: trueで型チェックとそのメモリを飛ばせますが、型のエラーがビルドに通ります。別のステップで型チェックしていないかぎり、Next.js は勧めていません。
メモリの多いマシンで動かす
| ランナー | CPU とメモリ | 使える人 |
|---|---|---|
GitHub の ubuntu-latest(プライベートリポジトリ) | 2 CPU・8 GB | だれでも |
GitHub の ubuntu-latest(公開リポジトリ) | 4 CPU・16 GB | 公開リポジトリ |
| GitHub の大きいランナー、4 コアか 8 コア | 16 GB か 32 GB | GitHub Team と Enterprise Cloud の組織、分課金(大きいランナー) |
Skipbox の skipbox-8x16 | 8 vCPU・16 GB | 組織と個人アカウント、月 12,000 円 |
Skipbox の skipbox-16x32 | 16 vCPU・32 GB | 組織と個人アカウント、月 23,000 円 |
月 20,000分なら、GitHub の 8 コアのランナーは 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。、Skipbox M は 12,000 円。16 コアなら 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。と、L の 23,000 円です。GitHub の額は、GitHub Team に含まれる無料分を引いたあとの請求です。
Skipbox が Next.js のビルドにすること
プランごとに、アカウント専用のマシンが付き、ジョブのあとも残ります。
- ビルドに足りるメモリを、ラベルで。M で 16 GB、L で 32 GB。ヒープもそれに合わせ、M なら
--max-old-space-size=12288などにします。 - パッケージのキャッシュはディスクに残ります。
~/.npm、pnpm のストア、各ツールの~/.cache、setup-nodeで入れた Node。npm ciはレジストリではなくそこから読みます。 actions/cacheの復元は、マシンから読みます。.next/cacheは追跡していないフォルダーで、チェックアウトの追跡していないファイルはジョブのたびに消すので、キャッシュのステップは残します。保存したものはマシンのそばに残り、容量は GitHub のリポジトリごと 10 GB より多く、復元は手元からの読み込みです。- コアを足しても定額。 コンパイルと静的ページの生成がコアを使い、実行時間は無制限です。
| ラベル | マシン | プラン |
|---|---|---|
skipbox | 4 vCPU・メモリ 16 GB | S、月 6,000 円 |
skipbox-8x16 | 8 vCPU・メモリ 16 GB | M、月 12,000 円 |
skipbox-16x32 | 16 vCPU・メモリ 32 GB | L、月 23,000 円 |
移行は runs-on を 1行書き換えるだけ
jobs:
build:
runs-on: skipbox-8x16 # ubuntu-latest から書き換える
env:
NODE_OPTIONS: --max-old-space-size=12288
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- run: npm ci
- run: npx next build
skipbox-8x16 はプラン M で動きます。トライアルで動くのは runs-on: skipbox です。
- Skipbox に GitHub でログインする
- Skipbox の GitHub アプリを入れて、使うリポジトリを選ぶ
runs-onを書き換えて push する
セキュリティ
- マシンはアカウントごとの専用です。ほかの会社のジョブと同じマシンで動くことはありません。
- ジョブが終わるたびに、ランナーの認証情報、プロセスとコンテナを消し、残したチェックアウトからも git の認証情報と追跡していないファイルを消します。「毎回クリーン」なら、ジョブごとに新しいマシンで動きます。
- 書き込み権限のない人のコード(フォークからのプルリクエストなど)は、使い捨ての VM で動きます。キャッシュは読めますが、書き換えられません。
くわしくはジョブの分離のしくみにあります。
Next.js のビルドで試す
カード不要で、7日間かジョブの合計 3,000分まで無料です。トライアルは runs-on: skipbox、メモリ 16 GB で、プライベートリポジトリの ubuntu-latest の 2倍です。キャッシュもメモリもそこで試し、さらにメモリが要るビルドはプラン L(skipbox-16x32、32 GB)に移してください。
よくある質問
GitHub Actions で next build が遅いのはなぜ?
たいていは .next/cache が空から始まるからです。Next.js はビルドのキャッシュを .next/cache に保存して次のビルドで使いますが、GitHub ホストランナーのジョブは新しい VM なので、.next/cache を引き継ぐステップがないと毎回まっさらなビルドになり、ログに No Cache Detected と出ます。ロックファイルとソースをキーにした actions/cache で .next/cache を引き継ぎます。残りの時間は、インストールと 2 CPU でのコンパイルです。
Next.js のビルドには、どのくらいのランナーが要る?
ビルドのいちばん多いときのメモリが入る大きさです。プライベートリポジトリの ubuntu-latest は 2 CPU・メモリ 8 GB で、大きな Next.js アプリの webpack のビルド、型チェック、ソースマップはそれを超えることがあります。GitHub の大きいランナーは 4 コアで 16 GB、8 コアで 32 GB ですが、使えるのは GitHub Team と Enterprise Cloud の組織だけで、分課金です。Skipbox なら runs-on: skipbox-8x16 で 8 vCPU・メモリ 16 GB が月 12,000 円、skipbox-16x32 で 16 vCPU・メモリ 32 GB が月 23,000 円です。
Next.js のビルドで JavaScript heap out of memory が出たら?
これは Node 自身のヒープの上限で、マシンのメモリではありません。NODE_OPTIONS=--max-old-space-size=<MiB> で、マシンのメモリより小さい値まで上げます。それで exit code 137 に変わったら、今度はマシンのメモリが尽きています。ビルドのメモリを減らす(experimental.webpackMemoryOptimizations、本番のソースマップを切る)か、メモリの多いマシンで動かします。
Next.js のビルドのメモリを減らすには?
Next.js のメモリのガイドによれば、experimental.webpackMemoryOptimizations(v15 から)を試す、webpack のビルドワーカーを使う(v14.1.0 から、独自の webpack の設定がなければ既定で有効)、productionBrowserSourceMaps と experimental.serverSourceMaps を切る、next build --experimental-debug-memory-usage で測る、です。typescript.ignoreBuildErrors で型チェックを飛ばすとメモリは減りますが、型のエラーがそのまま通るので、別のジョブで型チェックしているときだけにします。
Skipbox は .next/cache をジョブのあとも残す?
actions/cache のステップは残してください。.next/cache は追跡していないフォルダーで、チェックアウトの追跡していないファイルはジョブのたびに消します。変わるのは復元です。Skipbox の専用のマシンでは、actions/cache が保存したものはマシンのそばに残るので、復元はダウンロードではなく手元からの読み込みです。npm や pnpm のキャッシュ、setup-node で入れた Node、Docker のレイヤーは、ディスクそのものに残ります。
試すのにお金はかかる?
かかりません。カード不要で、7日間かジョブの合計 3,000分まで無料です。トライアルは 4 vCPU・メモリ 16 GB です。プライベートリポジトリの ubuntu-latest(8 GB)の 2倍で、GitHub の 4コアのより大きなランナーと同じです。キャッシュもメモリもそこで試せます。さらにメモリが要るビルドは、プラン L を選んでラベルを skipbox-16x32(32 GB)に書き換えてください。
2026年11月13日 更新