Menu

メモリ使用量の最適化方法

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

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

依存関係の数を減らす

大量の依存関係を持つアプリケーションはより多くのメモリを使用します。

Bundle Analyzerを使用すると、アプリケーション内の大きな依存関係を調査し、パフォーマンスとメモリ使用量を改善するために削除できる可能性のあるものを特定できます。

experimental.webpackMemoryOptimizationsを試す

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

補足: この機能は現在、より多くのプロジェクトでまず試験的に使用するための実験的機能ですが、リスクは低いと考えられています。

--experimental-debug-memory-usageフラグを付けてnext buildを実行する

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

補足: この機能は、カスタムwebpack設定がない限り自動的に有効になるWebpackビルドワーカーオプションとは互換性がありません。

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

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

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

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以降では、--experimental-debug-memory-usageフラグを付けてnext buildを実行することで、ヒープスナップショットを取得しやすくなります。

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

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

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

Webpackビルドワーカー

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

このオプションは、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',
      })
    }
    // 重要:変更した設定を返す
    return config
  },
}
 
export default nextConfig

静的解析を無効にする

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

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    // 警告:これにより、プロジェクトにESLintエラーがあっても本番ビルドが正常に完了できるようになります。
    ignoreDuringBuilds: true,
  },
  typescript: {
    // !! 警告 !!
    // プロジェクトに型エラーがあっても本番ビルドが正常に完了することを
    // 危険を承知で許可します。
    // !! 警告 !!
    ignoreBuildErrors: true,
  },
}
 
export default nextConfig

これにより、型エラーやリントの問題によって不具合のあるデプロイが発生する可能性があることに注意してください。 静的解析が完了した後にのみビルドを本番環境にプロモートすることを強くお勧めします。 Vercelにデプロイする場合は、カスタムタスクが成功した後にビルドを本番環境にプロモートする方法を学ぶためにステージングデプロイメントのガイドをご覧ください。

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

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

Next.js設定にproductionBrowserSourceMaps: falseexperimental.serverSourceMaps: falseを追加することで、ソースマップの生成を無効にできます。

補足: 一部のプラグインはソースマップを有効にすることがあり、無効にするにはカスタム設定が必要な場合があります。

Edgeのメモリ問題

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