コンテンツにスキップ
App Routerガイドメモリ使用量

メモリ使用量を最適化する方法

アプリケーションが成長し、機能が豊富になるにつれて、ローカルでの開発時や本番ビルドの作成時に、より多くのリソースを必要とする場合があります。

Next.jsにおけるメモリを最適化し、一般的なメモリの問題に対処するための戦略とテクニックを探ってみましょう。

依存関係の数を減らす

依存関係が多いアプリケーションは、より多くのメモリを使用します。

バンドルアナライザーは、パフォーマンスとメモリ使用量を改善するために削除できるアプリケーション内の大きな依存関係を調査するのに役立ちます。

experimental.webpackMemoryOptimizationsを試す

v15.0.0以降、next.config.jsファイルにexperimental.webpackMemoryOptimizations: trueを追加することで、Webpackの動作を変更し、最大メモリ使用量を削減できます。ただし、コンパイル時間はわずかに増加する可能性があります。

知っておくと便利: この機能は現在実験的であり、まずより多くのプロジェクトでテストされますが、リスクは低いと考えられています。

--experimental-debug-memory-usagenext buildを実行する

14.2.0以降、next build --experimental-debug-memory-usageを実行すると、ビルド中にメモリ使用量に関する情報(ヒープ使用量やガベージコレクション統計など)が継続的に表示されるモードでビルドを実行できます。メモリ使用量が設定された制限に近づくと、自動的にヒープスナップショットも取得されます。

知っておくと便利: この機能は、カスタムwebpack構成がない限り自動的に有効になるWebpackビルドワーカーオプションと互換性がありません。

ヒーププロファイルを記録する

メモリの問題を探るために、Node.jsからヒーププロファイルを記録し、Chrome DevToolsで読み込んで、メモリリークの潜在的な原因を特定できます。

ターミナルで、Next.jsビルドを開始する際に、Node.jsに--heap-profフラグを渡します。

node --heap-prof node_modules/next/dist/bin/next build

ビルドの最後に、Node.jsによって.heapprofileファイルが作成されます。

Chrome DevToolsで、メモリタブを開き、「プロファイルの読み込み」ボタンをクリックしてファイルを視覚化できます。

ヒープのスナップショットを分析する

インスペクターツールを使用して、アプリケーションのメモリ使用量を分析できます。

next buildまたはnext devコマンドを実行する際に、コマンドの先頭にNODE_OPTIONS=--inspectを追加します。これにより、デフォルトポートでインスペクターエージェントが公開されます。ユーザーコードが開始される前にブレークしたい場合は、代わりに--inspect-brkを渡すことができます。プロセスが実行中に、Chrome DevToolsなどのツールを使用してデバッグポートに接続し、ヒープのスナップショットを記録および分析して、保持されているメモリを確認できます。

14.2.0以降、next build--experimental-debug-memory-usageフラグと共に実行して、ヒープスナップショットを簡単に取得することもできます。

このモードで実行中に、いつでもプロセスにSIGUSR2シグナルを送信できます。すると、プロセスはヒープスナップショットを取得します。

ヒープスナップショットはNext.jsアプリケーションのプロジェクトルートに保存され、Chrome DevToolsなどの任意のヒープアナライザーで読み込んで、保持されているメモリを確認できます。このモードはまだWebpackビルドワーカーとは互換性がありません。

ヒープスナップショットの記録と分析方法を参照してください。

Webpackビルドワーカー

Webpackビルドワーカーを使用すると、Webpackコンパイルを別のNode.jsワーカー内で実行できるため、ビルド中のアプリケーションのメモリ使用量を削減できます。

このオプションは、v14.1.0以降、アプリケーションにカスタムWebpack構成がない場合にデフォルトで有効になります。

古いバージョンのNext.jsを使用している場合や、カスタムWebpack構成がある場合は、next.config.js内のexperimental.webpackBuildWorker: trueを設定することで、このオプションを有効にできます。

知っておくと便利: この機能は、すべてのカスタムWebpackプラグインと互換性がない場合があります。

Webpackキャッシュを無効にする

Webpackキャッシュは、ビルドの速度を向上させるために、生成されたWebpackモジュールをメモリ内またはディスクに保存します。これはパフォーマンスに役立ちますが、キャッシュされたデータを保存するためにアプリケーションのメモリ使用量も増加します。

アプリケーションにカスタムWebpack構成を追加することで、この動作を無効にできます。

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (
    config,
    { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
  ) => {
    if (config.cache && !dev) {
      config.cache = Object.freeze({
        type: 'memory',
      })
    }
    // Important: return the modified config
    return config
  },
}
 
export default nextConfig

静的解析を無効にする

型チェックは、特に大規模なプロジェクトでは多くのメモリを必要とする場合があります。しかし、ほとんどのプロジェクトには、これらのタスクをすでに処理している専用のCIランナーがあります。「Running TypeScript」ステップ中にビルドでメモリ不足の問題が発生した場合、ビルド中にこのタスクを無効にすることができます。

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!
    ignoreBuildErrors: true,
  },
}
 
export default nextConfig

これにより、型エラーによる誤ったデプロイが発生する可能性があることに注意してください。静的解析が完了した後にのみ、ビルドを本番環境にデプロイすることを強くお勧めします。Vercelにデプロイする場合、カスタムタスクが成功した後にビルドを本番環境に昇格させる方法については、ステージングデプロイのガイドを参照してください。

ソースマップを無効にする

ソースマップの生成は、ビルドプロセス中に余分なメモリを消費します。

productionBrowserSourceMaps: falseおよびexperimental.serverSourceMaps: falseをNext.js構成に追加することで、ソースマップ生成を無効にできます。

cacheComponents機能を使用する場合、Next.jsはnext buildのプリレンダリングフェーズ中にデフォルトでソースマップを使用します。そのフェーズ中に(「Generating static pages」の後)一貫してメモリの問題が発生する場合は、enablePrerenderSourceMaps: falseをNext.js構成に追加して、そのフェーズでのソースマップを無効にしてみてください。

知っておくと便利: 一部のプラグインはソースマップを有効にする場合があり、無効にするにはカスタム構成が必要になる場合があります。

Edgeメモリの問題

Next.js v14.1.3では、Edgeランタイム使用時のメモリの問題が修正されました。このバージョン(またはそれ以降)に更新して、問題が解決するかどうかを確認してください。

エントリの事前読み込み

Next.jsサーバーが起動すると、各ページのJavaScriptモジュールをリクエスト時にではなく、メモリに事前読み込みます。

この最適化により、応答時間が短縮されますが、初期メモリフットプリントは大きくなります。

この最適化を無効にするには、experimental.preloadEntriesOnStartフラグをfalseに設定します。

next.config.ts
import type { NextConfig } from 'next'
 
const config: NextConfig = {
  experimental: {
    preloadEntriesOnStart: false,
  },
}
 
export default config

Next.jsはこれらのJavaScriptモジュールをアンロードしないため、この最適化が無効になっていても、すべてのページが最終的にリクエストされた場合、Next.jsサーバーのメモリフットプリントは最終的に同じになります。