デプロイ
おめでとうございます!Next.js アプリケーションをデプロイする準備が整いました。このページでは、Next.js Build API を使ってマネージドまたはセルフホストでデプロイする方法を説明します。
プロダクションビルド
next build
を実行すると本番環境用に最適化されたバージョンのアプリケーションが生成されます。HTML、CSS、JavaScript ファイルは、お客様のページに基づいて作成されます。
JavaScript コードはコンパイルされ、ブラウザバンドルは最高のパフォーマンスを達成し、すべてのモダンブラウザをサポートするために最小化されています。
Next.js は、マネージド Next.js とセルフホスト Next.js で使用される標準のデプロイメント出力を生成します。これにより、両方のデプロイ方法ですべての機能がサポートされます。次のメジャーバージョンでは、この出力をビルド出力 API 仕様に変換する予定です。
Vercel によるマネージドな Next.js
Next.js の開発・保守を行う Vercel は、Next.js アプリケーションのためのマネージドインフラストラクチャと開発者体験プラットフォームを提供します。
Vercel へのデプロイはゼロコンフィギュレーションで、スケーラビリティ、可用性、パフォーマンスがグローバルに強化されます。ただし、セルフホストでも Next.js の機能はすべてサポートされます。
Vercel で Next.js の詳細をご覧いただくか、無料でテンプレートをデプロイしてお試しください。
セルフホスティング
Next.js をセルフホスティングするには、3 つの方法があります:
Node.js サーバー
Next.js は、Node.js をサポートしているホスティングプロバイダーにデプロイできます。
この場合は、package.json
に "build"
と "start"
スクリプトがあることを確認してください:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
次 に、npm run build
を実行してアプリケーションをビルドします。最後に、npm run start
を実行して Node.js サーバーを起動します。このサーバーは Next.js のすべての機能をサポートしています。
Docker Image
Next.js は、Dockerコンテナをサポートするホスティングプロバイダにデプロイできます。KubernetesやHashiCorp Nomadのようなコンテナ・オーケストレータにデプロイする場合にも、任意のクラウドプロバイダの単一ノード内で実行する場合にも、この方法を使用できます。
- あなたのマシンにDocker をインストールする
- with-docker のサンプルをクローンする
- コンテナをビルドする:
docker build -t nextjs-docker .
- コンテナを実行する:
docker run -p 3000:3000 nextjs-docker
複数の環境で異なる環境変数を使用する必要がある場合は、with-docker-multi-envの例を参照してください。
静的な HTML のエクスポート
Next.js は、静的サイトまたはシングルページアプリケーション(SPA)として開始し、その後オプションでサーバーを必要とする機能を使用するようにアップグレードすることができます。
Next.js はこの静的エクスポートをサポートしているので、HTML/CSS/JS の静的アセットを提供できるウェブサーバーであれば、どこにでもデプロイしてホストできます。これには、AWS S3、Nginx、Apache などのツールが含まれます。
静的エクスポートとして実行すると、サーバーを必要とする Next.js の機能はサポートされません。詳細はこちら。
Good to know
- Server Component は静的エクスポートでサポートされています。
Features
画像最適化
next/image
を使用した画像最適化は、next start
を使用してデプロイする場合、設定なしでセルフホストで動作します。画像の最適化を別のサービスで行いたい場合は、イメージローダーを設定できます。
画像の最適化は、next.config.js
でカスタム画像ローダーを定義することで、静的エクスポートで使用できます。画像の最適化は、ビルド時ではなく、実行時に行われることに注意してください。
Good to konw:
- セルフホスティングの場合は、プロジェクトディレクトリで
npm install sharp
を実行して、本番環境でよりパフォーマンスの高い画像最適化のために sharp をインストールすることを検討してください。Linux プラットフォームでは、過剰なメモリ使用を防ぐためにsharp
の追加設定が必要になる場合があります。- 最適化された画像のキャッシュ動作と、TTL の設定方法について詳しく説明します。
- 画像最適化を無効にしても、
next/image
を使用する他の利点を維持することもできます。例えば、自分で画像を個別に最適化する場合などです。
Middleware
next start
を使用してデプロイする場合、Middleware は設定なしでセルフホストで動作します。着信リクエストにアクセスする必要があるため、静的エクスポートを使用する場合はサポートされません。
Middleware は、利用可能なすべての Node.js API のサブセットであるランタイムを使用し、アプリケーション内のすべてのルートまたはアセットの前で実行される可能性があるため、低レイテンシを確保するのに役立ちます。このランタイムは "エッジで "実行する必要はなく、単一領域のサーバーで動作する。複数のリージョンでミドルウェアを実行するには、追加の設定とインフラストラクチャが必要です。
すべての Node.js API を必要とするロジックを追加する(または外部パッケージを使用する)場合は、このロジックを Server Component としてレイアウトに移動することができます。例えば、ヘッダのチェックやリダイレクトなどです。next.config.js
を通して、ヘッダ、クッキー、クエリパラメータを使ってリダイレクトや書き換えを行うこともできます。それでもうまくいかない場合は、カスタムサーバーを使うこともできます。
環境変数
Next.js は、ビルド時と実行時の両方の環境変数をサポートできる。
デフォルトでは、環境変数はサーバーでのみ利用可能です。環境変数をブラウザに公開するには、NEXT_PUBLIC
を先頭につける必要があります。ただし、これらの公開環境変数は next build
時に JavaScript バンドルにインライン化されます。
実行時環境変数を読み込むには、getServerSideProps
を使用するか、App Router を段階的に採用することをお勧めします。App Router を使えば、動的レンダリング中にサーバー上の環境変数を安全に読み取ることができる。これにより、異なる値を持つ複数の環境を通して昇格させることができる単一の Docker イメージを使用することができます。
import { unstable_noStore as noStore } from 'next/cache';
export default function Component() {
noStore();
// cookies(), headers(), and other dynamic functions
// will also opt into dynamic rendering, making
// this env variable is evaluated at runtime
const value = process.env.MY_VALUE
...
}
Good to know:
register
関数を使えば、サーバー起動時にコードを実行できる。 runtimeConfig オプションは、スタンドアロン出力モードでは動作しないため、使用は推奨しない。代わりに、App Router を段階的に採用することを推奨する。
キャッシュと ISR
Next.js は、レスポンス、生成された静的ページ、ビルド出力、画像、フォント、スクリプトなどの静的アセットをキャッシュできます。
ページのキャッシュと再検証(ISR(Incremental Static Regeneration)または App Router の新しい関数を使用)は、同じ共有キャッシュを使用します。デフォルトでは、このキャッシュは Next.js サーバーのファイルシステム(ディスク)に保存されます。これは、Pages と App Router の両方を使用してセルフホストする場合に自動的に機能します。
キャッシュされたページやデータを耐久性のあるストレージに永続化したい場合や、Next.js アプリケーションの複数のコンテナやインスタンスでキャッシュを共有したい場合は、Next.js キャッシュの場所を設定できます。
自動キャッシュ
- Next.js は、本当にイミュータブルなアセットには、
Cache-Control
ヘッダーにpublic, max-age=31536000, immutable
を設定します。これは上書きできません。これらのイミュータブル ファイルは、ファイル名に SHA ハッシュが含まれているため、安全に無期限にキャッシュできます。例えば、静的画像のインポートです。画像の TTL を設定できます。 - Incremental Static Regeneration (ISR)は
s-maxage: <revalidate in 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 をホスティングしている場合、各 Pod はキャッシュのコピーを持ちます。デフォルトではキャッシュが Pod 間で共有されないため、古いデータが表示されるのを防ぐには、Next.js キャッシュを設定してキャッシュハンドラを提供し、メモリ内キャッシュを無効にします。
セルフホスト時に ISR/Data Cache の場所を設定するには、next.config.js
ファイルにカスタムハンドラを設定します:
module.exports = {
experimental: {
incrementalCacheHandlerPath: require.resolve('./cache-handler.js'),
isrMemoryCacheSize: 0, // disable default in-memory caching
},
}
次に、例えばプロジェクトのルートに 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(tag) {
// 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.includes(tag)) {
cache.delete(key)
}
}
}
}
カスタムキャッシュハンドラを使用すると、Next.js アプ リケーションをホストするすべての Pod で一貫性を確保できます。たとえば、Redis や AWS S3 など、任意の場所にキャッシュ値を保存できます。
Good to know:
revalidatePath
はキャッシュ・タグの上にある便利なレイヤーです。revalidatePath
を呼び出すと、提供されたページのための特別なデフォルトタグでrevalidateTag
関数が呼び出されます。
ビルドキャッシュ
Next.js は next build
時に ID を生成し、どのバージョンのアプリケーションが提供されるかを識別します。同じビルドを使用して、複数のコンテナを起動する必要があります。
環境のステージごとに再構築する場合は、コンテナ間で使用する一貫したビルド ID を生成する必要があります。next.config.js
の generateBuildId
コマンドを使用します:
module.exports = {
generateBuildId: async () => {
// This could be anything, using the latest git hash
return process.env.GIT_HASH
},
}
Version Skew
Next.js は、version Skewのほとんどのインスタンスを自動的に軽減し、検出されると自動的にアプリケーションをリロードして新しいアセットを取得します。たとえば、ビルド ID に不一致がある場合、ページ間の遷移は、プリフェッチされた値を使用するのではなく、ハードナビゲーションを実行します。
アプリケーションがリロードされるとき、ページナビゲーション間で永続するように設計されていない場合、アプリケーションの状態が失われる可能性があります。例えば、URL ステートやローカルストレージを使用すると、ページ更新後もステートが持続します。しかし、useState
のようなコンポーネントの状態は、そのようなナビゲーションの際に失われます。
Vercel は、Next.js アプリケーションに追加のskew protectionを提供し、新しいビルドがデプロイされている間も、以前のビルドのアセットと関数が利用可能であることを保証します。
ストリーミングと Suspense
Next.js App Router は、セルフホスト時にストリーミング応答をサポートします。 Nginx や同様のプロキシを使用している場合は、バッファリングを無効にしてストリーミングを利用できるように設定する必要があります。
たとえば、Nginx で X-Accel-Buffering
を no
に設定することで、バッファリングを無効にできます:
module.exports = {
async headers() {
return [
{
source: '/:path*{/}?',
headers: [
{
key: 'X-Accel-Buffering',
value: 'no',
},
],
},
]
},
}
- Production Checklist: Next.js アプリケーションを本番環境に導入する前に、最高のパフォーマンスとユーザーエクスペリエンスを確保するための推奨事項です。
- 静的エクスポート: Next.js は、静的サイトまたはシングルページアプリケーション(SPA)として開始し、その後オプションでサーバーを必要とする機能を使用するようにアップグレードすることができます。