デプロイ
おめでとうございます。いよいよプロダクション環境に出荷する時が来ました。
マネージドNext.jsをVercelでデプロイすることも、Node.jsサーバー、Dockerイメージ、さらには静的HTMLファイルでセルフホストすることもできます。next start
を使用してデプロイする場合、すべてのNext.js機能がサポートされます。
プロダクションビルド
next build
を実行すると、アプリケーションの最適化バージョンが生成されます。HTML、CSS、JavaScriptファイルはページに基づいて作成されます。JavaScriptはコンパイルされ、ブラウザバンドルは最高のパフォーマンスを実現し、すべての最新ブラウザに対応するために、Next.js Compilerを使用して最小化されます。
Next.jsは、マネージドおよびセルフホストNext.jsの両方で使用される標準のデプロイメント出力を生成します。これにより、両方のデプロイメント方法で機能がサポートされるようになります。次のメジャーバージョンでは、この出力をBuild Output API仕様に変換する予定です。
VercelでのマネージドNext.js
Next.jsの作成者でありメンテナーであるVercelは、Next.jsアプリケーションのためのマネージドインフラストラクチャと開発者体験プラットフォームを提供しています。
Vercelへのデプロイはゼロ設定で、グローバルでのスケーラビリティ、可用性、パフォーマンスの向上を提供します。ただし、すべてのNext.js機能はセルフホスト時にもサポートされます。
Next.js on Vercelについてもっと学ぶか、試してみるためにテンプレートを無料でデプロイしてください。
セルフホスティング
Next.jsをセルフホストする方法は3種類あります:
🎥 ご覧ください: Next.jsのセルフホスティングについてもっと学ぶ → YouTube (45 minutes).
次のプロバイダーを使ったコミュニティが維持するデプロイの例があります:
Node.jsサーバー
Next.jsはNode.jsをサポートする任意のホスティングプロバイダーにデプロイ可能です。package.json
に"build"
と"start"
スクリプトを必ず含めてください:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
次に、アプリケーションをビルドするためにnpm run build
を実行します。最後に、Node.jsサーバーを開始するためにnpm run start
を実行します。このサーバーはすべての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の機能はサポートされません。詳細はこちら.
Good to know:
- Server Componentsは静的エクスポートでサポートされています。
特徴
画像最適化
next/image
による画像最適化は、next start
を使ってデプロイする際にセルフホストでゼロ設定で動作します。画像を最適化する別のサービスを使用する場合、画像ローダーを設定することができます。
画像最適化はnext.config.js
でカスタム画像ローダーを定義することで、静的エクスポートと一緒に使用できます。ただし、画像はビルド時ではなくランタイムで最適化されます。
Good to know:
ミドルウェア
ミドルウェアは、next start
を使用してデプロイする際、セルフホストでゼロ設定で機能します。受信リクエストへのアクセスが必要なため、静的エクスポートを使用する場合はサポートされません。
ミドルウェアは、すべての利用可能なNode.js APIのサブセットであるruntimeを使用しており、低遅延を保証するため、アプリケーション内のすべてのルートまたはアセットの前で実行される可能性があります。このランタイムは「エッジ」で実行する必要はなく、単一リージョンのサーバーで動作します。ミドルウェアを複数のリージョンで実行するには、追加の設定とインフラストラクチャが必要です。
すべてのNode.js APIを必要とするロジックを追加したり、外部パッケージを使用したりする場合、このロジックをレイアウト内でサーバーコンポーネントとして移動することができるかもしれません。たとえば、ヘッダーを確認したり、リダイレクトしたりする場合です。next.config.js
を通じてヘッダー、クッキー、クエリパラメーターを使用してリダイレクトや書き換えすることもできます。それがうまくいかない場合は、カスタムサーバーを使用することもできます。
環境変数
Next.jsはビルド時およびランタイムの環境変数の両方をサポートできます。
デフォルトでは、環境変数はサーバーでのみ利用可能です。 環境変数をブラウザに公開するには、NEXT_PUBLIC_
で始める必要があります。ただし、これらの公開された環境変数は、next build
時にJavaScriptバンドルにインライン化されます。
サーバー上で動的レンダリング中に環境変数を安全に読み取ることができます。
- TypeScript
- JavaScript
import { connection } from 'next/server'
export default async function Component() {
await connection()
// cookies, headers, and other Dynamic APIs
// will also opt into dynamic rendering, meaning
// this env variable is evaluated at runtime
const value = process.env.MY_VALUE
// ...
}
import { connection } from 'next/server'
export default async function Component() {
await connection()
// cookies, headers, and other Dynamic APIs
// will also opt into dynamic rendering, meaning
// this env variable is evaluated at runtime
const value = process.env.MY_VALUE
// ...
}
これにより、異なる値を持つ複数の環境にプロモートできる単一のDockerイメージを使用できます。
Good to know:
register
関数を利用して、サーバーの起動時にコードを実行することができます。- runtimeConfigオプションの使用はお勧めしません。これはスタンドアロン出力モードと互換性がありません。その代わりに、段階的にApp Routerを採用することをお勧めします。
キャッシングとISR
Next.jsは、応答、生成された静的ページ、ビルド出力、画像、フォント、スクリプトなどの他の静的アセットをキャッシュできます。
ページのキャッシングと再検証(Incremental Static Regenerationを使用)は同じ共有キャッシュを使用します。デフォルトでは、このキャッシュはNext.jsサーバー上のファイルシステム(ディスク上)に保存されます。セルフホスティング時に自動的に動作します。Pages RouterとApp Routerの両方で使用されます。
Next.jsのキャッシュの場所を設定して、キャッシュされたページとデータを耐久性のあるストレージに保存したり、複数のコンテナやNext.jsアプリケーションのインスタンス間でキャッシュを共有したりすることができます。
自動キャッシング
- Next.jsは、真に不変のアセットに
public, max-age=31536000, immutable
のCache-Control
ヘッダーを設定します。これは上書きできません。これらの不変のファイルはファイル名に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の両方に適用されます。また、Draft Modeも含まれます。
静的アセット
異なるドメインまたはCDNに静的アセットをホストしたい場合、next.config.js
のassetPrefix
構成を使用できます。Next.jsはこのアセットプレフィックスを使用してJavaScriptまたはCSSファイルを取得します。アセットを異なるドメインに分けることには、DNSとTLSの解決に追加の時間がかかるという欠点があります。
キャッシュ設定
デフォルトでは、生成されたキャッシュアセットはメモリ(デフォルトは50MB)およびディスク上に保存されます。Kubernetesのようなコンテナオーケストレーションプラットフォームを使用してNext.jsをホスティングする場合、各ポッドにはそのコピーのキャッシュがあります。ポッド間でキャッシュが共有されていないため、古いデータが表示されるのを防ぐため、Next.jsキャッシュを設定してキャッシュハンドラーを提供し、メモリキャッシュを無効にすることができます。
セルフホスティング時にISR/Data Cacheの場所を設定するには、next.config.js
ファイルでカスタムハンドラーを指定できます:
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // デフォルトのメモリキャッシュを無効化
}
次に、プロジェクトのrootディレクトリでcache-handler.js
を作成します。例:
const cache = new Map()
module.exports = class CacheHandler {
constructor(options) {
this.options = options
}
async get(key) {
// このデータはどこにでも保存される可能性があります
return cache.get(key)
}
async set(key, data, ctx) {
// このデータはどこにでも保存される可能性があります
cache.set(key, {
value: data,
lastModified: Date.now(),
tags: ctx.tags,
})
}
async revalidateTag(tags) {
// tags は文字列または文字列の配列です
tags = [tags].flat()
// キャッシュ内のすべてのエントリを反復処理
for (let [key, value] of cache) {
// 値のタグが指定されたタグを含む場合、このエントリを削除
if (value.tags.some((tag) => tags.includes(tag))) {
cache.delete(key)
}
}
}
}
カスタムキャッシュハンドラーを使用すると、Next.jsアプリケーションをホストしているすべてのポッド間で一貫性を保証できます。たとえば、キャッシュされた値をRedisやAWS S3など、どこにでも保存できます。
Good to know:
revalidatePath
はキャッシュタグの上にある便利なレイヤーです。revalidatePath
を呼び出すと、提供されたページの特別なデフォルトタグでrevalidateTag
関数が呼び出されます。
ビルドキャッシュ
Next.jsは、サーバーに提供されるアプリケーションのバージョンを識別するためにnext build
中にIDを生成します。同じビルドは複数のコンテナを使用して起動されるべきです。
環境の各ステージごとに再ビルドする場合、コンテナ間で使用するために一貫したビルドIDを生成する必要があります。next.config.js
でgenerateBuildId
コマンドを使用します:
module.exports = {
generateBuildId: async () => {
// これを何でも可能です。最新のgitハッシュを使用する
return process.env.GIT_HASH
},
}
バージョンスキュー
Next.jsは、バージョンスキューの多くのインスタンスを自動的に緩和し、新しいアセットを取得するためにアプリケーションを自動的にリロードします。たとえば、deploymentId
の不一致がある場合、ページ間の遷移は事前にフェッチされた値を使用するのではなく、ハードナビゲーションを行います。
アプリケーションがリロードされると、ページナビゲーション間で永続化されるように設計されていない場合、アプリケーションの状態が失われる可能性があります。たとえば、URLの状態やローカルストレージを使用することで、ページのリフレッシュ後も状態を保持できます。しかし、useState
のようなコンポーネントの状態は、そのようなナビゲーションで失われます。
Vercelは、Next.jsアプリケーションの追加のスキュー保護を提供し、新しいバージョンがデプロイされた後でも、旧バージョンのアセットや関数を依然として古いクライアントが利用できるようにします。
各リクエストが?dpl
クエリ文字列またはx-deployment-id
ヘッダーを使用するようにするには、next.config.js
ファイルでdeploymentId
プロパティを手動で設定できます。
ストリーミングとサスペンス
Next.jsのApp Routerは、セルフホスティング時にストリーミングレスポンスをサポートしています。Nginxまたは同様のプロキシを使用している場合、ストリーミングを有効にするにはバッファリングを無効にするように設定する必要があります。
たとえば、NginxでX-Accel-Buffering
をno
に設定することでバッファリングを無効にすることができます:
module.exports = {
async headers() {
return [
{
source: '/:path*{/}?',
headers: [
{
key: 'X-Accel-Buffering',
value: 'no',
},
],
},
]
},
}
部分的なプリレンダリング
部分的なプリレンダリング(実験的)は、Next.jsではデフォルトで機能し、CDNの機能ではありません。これはNode.jsサーバーとしてデプロイされた場合(next start
経由)やDockerコンテナと一緒に使用された場合に含まれます。
CDNの使用
Next.jsアプリケーションの前にCDNを使用する場合、動的APIがアクセスされると、ページはCache-Control: private
応答ヘッダーを含めます。これにより、生成されたHTMLページがキャッシュ可能でないことが保証されます。ページが完全に静的にプリレンダリングされている場合、Cache-Control: public
が含まれ、ページがCDN上でキャッシュ可能になります。
静的と動的コンポーネントの両方が混在する必要がない場合、ルート全体を静的にして、CDN上で出力HTMLをキャッシュすることができます。この自動静的最適化は、動的APIが使用されていない場合にnext build
を実行するときにデフォルトの動作です。