コンテンツへスキップ

デプロイ

おめでとうございます。本番環境へのリリース準備が整いました。

VercelによるマネージドNext.jsにデプロイするか、Node.jsサーバー、Dockerイメージ、または静的HTMLファイルでセルフホスティングできます。next startを使用してデプロイする場合、すべてのNext.js機能がサポートされます。

本番ビルド

next buildを実行すると、本番環境向けに最適化されたアプリケーションバージョンが生成されます。HTML、CSS、およびJavaScriptファイルは、ページに基づいて作成されます。JavaScriptは**コンパイル**され、ブラウザバンドルはNext.jsコンパイラを使用して**縮小**され、最高の性能を実現し、すべての最新のブラウザをサポートします。

Next.jsは、マネージド型とセルフホスティング型のNext.jsで使用される標準的なデプロイ出力を作成します。これにより、両方のデプロイ方法で、すべての機能がサポートされます。次のメジャーバージョンでは、この出力をBuild Output API仕様に変換する予定です。

VercelによるマネージドNext.js

Vercelは、Next.jsの開発者およびメンテナであり、Next.jsアプリケーションのためのマネージドインフラストラクチャと開発者エクスペリエンスプラットフォームを提供しています。

Vercelへのデプロイはゼロコンフィグレーションであり、グローバルなスケーラビリティ、可用性、パフォーマンスのための追加の機能強化を提供します。ただし、セルフホスティングの場合でも、すべてのNext.js機能は引き続きサポートされます。

Vercel での Next.js について詳しくは、Vercel 上の Next.js を参照するか、テンプレートを無料でデプロイして試してみてください。

セルフホスティング

Next.js は3つの異なる方法でセルフホストできます。

🎥 動画:Next.js のセルフホスティングについて詳しくは → YouTube (45分)

Node.js サーバー

Next.js は、Node.js をサポートする任意のホスティングプロバイダーにデプロイできます。`package.json` に `build` スクリプトと `start` スクリプトが含まれていることを確認してください。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

次に、`npm run build` を実行してアプリケーションをビルドします。最後に、`npm run start` を実行して Node.js サーバーを起動します。このサーバーは、すべての Next.js 機能をサポートしています。

Docker イメージ

Next.js は、Docker コンテナをサポートする任意のホスティングプロバイダーにデプロイできます。この方法は、Kubernetesなどのコンテナオーケストレーターにデプロイする場合、または任意のクラウドプロバイダーでコンテナ内で実行する場合に使用できます。

  1. お使いのマシンに Docker をインストールします。
  2. サンプルをクローンします(またはマルチ環境のサンプル)。
  3. コンテナをビルドします:`docker build -t nextjs-docker .`
  4. コンテナを実行します:`docker run -p 3000:3000 nextjs-docker`

Docker を介した Next.js は、すべての Next.js 機能をサポートしています。

静的 HTML エクスポート

Next.js を使用すると、静的サイトまたはシングルページアプリケーション (SPA) として開始し、後で必要に応じてサーバーを必要とする機能にアップグレードできます。

Next.js はこの静的エクスポートをサポートしているため、HTML/CSS/JS 静的アセットを提供できる任意の Web サーバーにデプロイしてホストできます。これには、AWS S3、Nginx、Apache などのツールが含まれます。

静的エクスポートとして実行すると、サーバーを必要とする Next.js の機能はサポートされません。詳細はこちら

知っておくと役立つ情報

機能

画像最適化

画像最適化 は、`next/image` を使用して、`next start` を使用してデプロイする場合、構成なしでセルフホストで動作します。画像を最適化する別のサービスを使用する場合は、画像ローダーを構成できます。

画像最適化は、`next.config.js` でカスタム画像ローダーを定義することで、静的エクスポートで使用できます。ただし、画像はビルド時ではなく、ランタイム時に最適化されることに注意してください。

知っておくと役立つ情報

  • glibc ベースの Linux システムでは、画像最適化には、過剰なメモリ使用を防ぐために追加の構成が必要になる場合があります。
  • 最適化された画像のキャッシング動作と TTL の構成方法について詳しくは、こちらをご覧ください。
  • また、画像最適化を無効化して、`next/image` の他の利点を維持することもできます。たとえば、画像を自分で別途最適化する場合などです。

ミドルウェア

ミドルウェア は、`next start` を使用してデプロイする場合、構成なしでセルフホストで動作します。受信リクエストへのアクセスが必要なため、静的エクスポートを使用する場合はサポートされていません。

ミドルウェアは、低遅延を確保するために、使用可能なすべての Node.js API のサブセットであるランタイムを使用します。これは、アプリケーションのすべてのルートまたはアセットの前に実行される可能性があるためです。このランタイムは「エッジで」実行する必要はなく、単一リージョンのサーバーで動作します。ミドルウェアを複数のリージョンで実行するには、追加の構成とインフラストラクチャが必要です。

すべての Node.js API を必要とするロジックを追加する場合(または外部パッケージを使用する場合)、このロジックをレイアウトサーバーコンポーネントとして移動できます。たとえば、ヘッダーを確認してリダイレクトします。リダイレクトまたは書き換えには、ヘッダー、Cookie、またはクエリパラメーターを`next.config.js` を使用することもできます。それでもうまくいかない場合は、カスタムサーバーを使用することもできます。

環境変数

Next.jsは、ビルド時と実行時の両方で環境変数をサポートできます。

デフォルトでは、環境変数はサーバーでのみ利用可能です。ブラウザで環境変数を使用するには、`NEXT_PUBLIC_`というプレフィックスを付ける必要があります。ただし、これらの公開環境変数は、`next build`の実行中にJavaScriptバンドルにインライン化されます。

実行時環境変数を読み取るには、`getServerSideProps`を使用するか、App Routerを段階的に導入することをお勧めします。

これにより、異なる値を持つ複数の環境でプロモーションできる単一のDockerイメージを使用できます。

知っておくと役立つ情報

  • `register`関数を使用して、サーバーの起動時にコードを実行できます。
  • runtimeConfigオプションの使用はお勧めしません。これはスタンドアロン出力モードでは機能しないためです。段階的な導入としてApp Routerを使用することをお勧めします。

キャッシュとISR

Next.jsは、レスポンス、生成された静的ページ、ビルド出力、画像、フォント、スクリプトなどのその他の静的アセットをキャッシュできます。

ページのキャッシュと再検証(Incremental Static Regenerationを使用)は、同じ共有キャッシュを使用します。デフォルトでは、このキャッシュはNext.jsサーバーのファイルシステム(ディスク上)に保存されます。これは、PagesとApp Routerの両方を使用してセルフホスティングする場合に自動的に機能します

キャッシュされたページとデータを永続ストレージに保存したり、Next.jsアプリケーションの複数のコンテナやインスタンス間でキャッシュを共有したい場合は、Next.jsキャッシュの場所を構成できます。

自動キャッシング

  • Next.jsは、真に不変のアセットに`public, max-age=31536000, immutable`の`Cache-Control`ヘッダーを設定します。これは上書きできません。これらの不変ファイルにはファイル名にSHAハッシュが含まれているため、無期限に安全にキャッシュできます。たとえば、静的画像インポート。画像のTTLは構成できます
  • Incremental Static Regeneration(ISR)は、`s-maxage: <getStaticPropsでの再検証時間>, stale-while-revalidate`の`Cache-Control`ヘッダーを設定します。この再検証時間は、`getStaticProps`関数で秒単位で定義されます。`revalidate: false`を設定すると、デフォルトで1年間のキャッシュ期間になります。
  • 動的にレンダリングされたページは、ユーザー固有のデータがキャッシュされないように、`private, no-cache, no-store, max-age=0, must-revalidate`の`Cache-Control`ヘッダーを設定します。これは、App RouterとPages Routerの両方に適用されます。ドラフトモードも含まれます。

静的アセット

異なるドメインまたはCDNで静的アセットをホストする場合は、`next.config.js`で`assetPrefix`設定を使用できます。Next.jsは、JavaScriptファイルまたはCSSファイルを取得する際にこのアセットプレフィックスを使用します。アセットを異なるドメインに分離すると、DNSとTLSの解決に余分な時間がかかるという欠点があります。

`assetPrefix`の詳細.

キャッシュの構成

デフォルトでは、生成されたキャッシュアセットはメモリ(デフォルトは50MB)とディスクに保存されます。Kubernetesなどのコンテナオーケストレーションプラットフォームを使用してNext.jsをホストしている場合、各ポッドにはキャッシュのコピーがあります。デフォルトではキャッシュがポッド間で共有されないため、古いデータが表示されるのを防ぐには、Next.jsキャッシュを構成してキャッシュハンドラーを提供し、メモリ内キャッシングを無効にすることができます。

セルフホスティング時のISR/データキャッシュの場所を構成するには、`next.config.js`ファイルでカスタムハンドラーを構成できます。

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
}

次に、プロジェクトのルートに`cache-handler.js`を作成します(例)

cache-handler.js
const cache = new Map()
 
module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }
 
  async get(key) {
    // This could be stored anywhere, like durable storage
    return cache.get(key)
  }
 
  async set(key, data, ctx) {
    // This could be stored anywhere, like durable storage
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }
 
  async revalidateTag(tags) {
    // tags is either a string or an array of strings
    tags = [tags].flat()
    // Iterate over all entries in the cache
    for (let [key, value] of cache) {
      // If the value's tags include the specified tag, delete this entry
      if (value.tags.some((tag) => tags.include(tag))) {
        cache.delete(key)
      }
    }
  }
}

カスタムキャッシュハンドラーを使用すると、Next.jsアプリケーションをホストするすべてのポッド間の一貫性を確保できます。たとえば、RedisやAWS S3などの任意の場所にキャッシュされた値を保存できます。

知っておくと役立つ情報

  • `revalidatePath`は、キャッシュタグの上位にある便利なレイヤーです。`revalidatePath`を呼び出すと、指定されたページの特別なデフォルトタグを使用して`revalidateTag`関数が呼び出されます。

ビルドキャッシュ

Next.jsは`next build`中に、提供されているアプリケーションのバージョンを識別するためのIDを生成します。同じビルドを使用して、複数のコンテナを起動する必要があります。

環境の各段階で再ビルドする場合は、コンテナ間で使用する一貫性のあるビルドIDを生成する必要があります。`next.config.js`で`generateBuildId`コマンドを使用します。

next.config.js
module.exports = {
  generateBuildId: async () => {
    // This could be anything, using the latest git hash
    return process.env.GIT_HASH
  },
}

バージョンずれ

Next.jsは、ほとんどのバージョンずれを自動的に軽減し、検出された場合に新しいアセットを取得するためにアプリケーションを自動的に再ロードします。たとえば、`deploymentId`に不一致がある場合、ページ間の遷移は、プリフェッチされた値を使用するのではなく、強制的なナビゲーションを実行します。

アプリケーションが再ロードされると、ページ間のナビゲーション間で永続化されない限り、アプリケーションの状態が失われる可能性があります。たとえば、URLの状態またはローカルストレージを使用すると、ページのリフレッシュ後も状態が保持されます。ただし、`useState`のようなコンポーネントの状態は、そのようなナビゲーションで失われます。

Vercelは、新しいバージョンがデプロイされた後でも、以前のバージョンのアセットと関数を古いクライアントが引き続き使用できるように、Next.jsアプリケーションの追加のスキュー保護を提供します。

`next.config.js`ファイルで`deploymentId`プロパティを手動で構成して、各リクエストで`?dpl`クエリ文字列または`x-deployment-id`ヘッダーのいずれかを使用するようにすることができます。

手動によるグレースフルシャットダウン

セルフホスティングの場合、`SIGTERM`または`SIGINT`シグナルでサーバーがシャットダウンしたときにコードを実行したい場合があります。

環境変数`NEXT_MANUAL_SIG_HANDLE`を`true`に設定し、`_document.js`ファイル内でそのシグナルのハンドラーを登録できます。環境変数は、`.env`ファイルではなく、`package.json`スクリプトに直接登録する必要があります。

参考情報: next dev では、手動によるシグナル処理は利用できません。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "NEXT_MANUAL_SIG_HANDLE=true next start"
  }
}
pages/_document.js
if (process.env.NEXT_MANUAL_SIG_HANDLE) {
  process.on('SIGTERM', () => {
    console.log('Received SIGTERM: cleaning up')
    process.exit(0)
  })
  process.on('SIGINT', () => {
    console.log('Received SIGINT: cleaning up')
    process.exit(0)
  })
}