デプロイ
おめでとうございます。いよいよ本番環境にデプロイする時が来ました。
Next.jsはVercelでマネージドサービスとしてデプロイするか、Node.jsサーバー、Dockerイメージ、または静的HTMLファイルとしてセルフホストできます。next start
を使用してデプロイする場合、すべてのNext.js機能がサポートされます。
プロダクションビルド
next build
を実行すると、本番環境向けに最適化されたアプリケーションが生成されます。ページに基づいてHTML、CSS、JavaScriptファイルが作成されます。JavaScriptはNext.jsコンパイラを使用してコンパイルされ、ブラウザバンドルは最小化され、最高のパフォーマンスを実現し、すべてのモダンブラウザをサポートします。
Next.jsは、マネージドNext.jsとセルフホスト型Next.jsで使用される標準的なデプロイ出力を作成します。これにより、両方のデプロイ方法ですべての機能がサポートされます。次のメジャーバージョンでは、この出力をBuild Output API仕様に変換する予定です。
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"
スクリプトがあることを確認してください。
{
"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などのコンテナオーケストレーターにデプロイする場合や、任意のクラウドプロバイダーのコンテナ内で実行する場合に使用できます。
- お使いのマシンにDockerをインストールします
- サンプルをクローンする (またはマルチ環境のサンプル)
- コンテナをビルドします:
docker build -t nextjs-docker .
- コンテナを実行します:
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
でカスタム画像ローダーを定義することで、静的エクスポートと一緒に使用できます。画像はビルド時ではなく、実行時に最適化されることに注意してください。
知っておくと良いこと
ミドルウェア
ミドルウェアは、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解決に余分な時間がかかるという欠点があります。
キャッシュの設定
デフォルトでは、生成されたキャッシュアセットはメモリ (デフォルトで50MB) とディスクに保存されます。Kubernetesのようなコンテナオーケストレーションプラットフォームを使用してNext.jsをホストしている場合、各Podはキャッシュのコピーを持ちます。デフォルトではキャッシュがPod間で共有されないため、古いデータが表示されるのを防ぐために、Next.jsのキャッシュを構成してキャッシュハンドラを提供し、インメモリキャッシュを無効にすることができます。
セルフホスティング時にISR/データキャッシュの場所を設定するには、next.config.js
ファイルでカスタムハンドラを設定できます。
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 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(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.includes(tag))) {
cache.delete(key)
}
}
}
// If you want to have temporary in memory cache for a single request that is reset
// before the next request you can leverage this method
resetRequestCache() {}
}
カスタムキャッシュハンドラを使用すると、Next.jsアプリケーションをホストするすべてのPod間で一貫性を確保できます。例えば、キャッシュされた値をRedisやAWS S3のような任意の場所に保存できます。
知っておくと良いこと
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
},
}
バージョンスキュー
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
では手動シグナルハンドリングは利用できません。
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "NEXT_MANUAL_SIG_HANDLE=true next start"
}
}
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)
})
}
本番環境チェックリスト
静的エクスポート
マルチゾーン
継続的インテグレーション (CI) ビルドキャッシュ
この情報は役に立ちましたか?