Deploying
おめでとうございます、production に出荷する時間です。
あなたは managed Next.js with Vercel を deploy することも、自己ホストすることもできます。それは Node.js server の上にあるか、Docker の image の中にあるか、あるいは静的な HTML ファイルでさえ可能です。next start
を使用してデプロイするとき、すべての Next.js の機能がサポートされます。
Production Builds
next build
を実行すると、あなたのアプリケーションの最適化された version が production 用に生成されます。HTML, CSS, JavaScript のファイルはあなたのページに基づいて作成されます。JavaScript はコンパイルされ、ブラウザのバンドルは Next.js Compiler を使用して圧縮されます。これにより、最高のパフォーマンスを実現し、すべての現代のブラウザをサポートします。
Next.js は、管理されたものと自己ホスティングされた Next.js の両方で使用される標準的なデプロイメント出力を生成します。これにより、どちらのデプロイメント方法でもすべての機能がサポートされることを保証します。次のメジャー version では、この出力を私たちの Build 出力 API 仕様 に変換する予定です。
Managed Next.js with Vercel
Vercel は、Next.js の制作者および管理者であり、Next.js アプリケーションのための管理されたインフラストラクチャと開発者エクスペリエンスプラットフォームを提供しています。
Vercel へのデプロイはゼロコンフィギュレーションで、スケーラビリティ、可用性、およびグローバルなパフォーマンス向上のための追加機能を提供します。しかし、自己ホスト時でも、すべての Next.js の機能は依然としてサポートされています。
Vercel の Next.js についてもっと学んだり、無料で template を deploy して試してみましょう。
Self-Hosting
あなたは 3 つの異なる方法で Next.js をセルフホストすることができます:
Node.js Server
Next.js は、Node.js をサポートしている任意のホスティングプロバイダにデプロイできます。あなたのpackage.json
が"build"
と"start"
の scripts を持っていることを確認してください:"
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
それから、アプリケーションを build するために npm run build
を実行します。最後に、 npm run start
を実行して、Node.js server を start させます。この server はすべての Next.js 機能をサポートします。
Docker Image
Next.js は Docker コンテナをサポートしている任意のホスティングプロバイダにデプロイできます。このアプローチは、Kubernetes などの container オーケストレータへデプロイする際や、任意のクラウドプロバイダ内の container で実行する際に使用できます。
- あなたのマシンに Install Docker をインストールしてください
- 私たちの例をクローンしてください (またはマルチ環境の例 )
- Build を使用して、あなたの container を作成します:
docker build -t nextjs-docker .
- あなたの container を実行してください:
docker run -p 3000:3000 nextjs-docker
Docker を通じての Next.js はすべての Next.js 機能をサポートします。
静的な HTML Export
Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server.
Next.js は、この静的な export をサポートしているため、HTML/CSS/JS の静的アセットを提供できる任意のウェブ server にデプロイおよびホスティングできます。これには、AWS S3、Nginx、または Apache のようなツールが含まれます。
静的な export として実行することは、server が require とされる Next.js の機能をサポートしていません。詳細を学ぶ。
Good to know:
- Server Components は静的 export でサポートされています。
Features
Image Optimization
Image Optimization は next/image
を通じて自己ホスティングでゼロ設定として動作し、next start
を使用してデプロイします。別のサービスを使用して画像を最適化したい場合は、image loader の設定を行うことができます。
Image Optimization は、カスタムの image loader をnext.config.js
で定義することにより、静的な export と共に使用できます。なお、イメージは build 中ではなく、runtime 中に最適化されることに注意してください。
Good to know:
- セルフホスティングの際には、プロジェクトディレクトリで
npm install sharp
を実行し、sharp
をインストールして、パフォーマンスの高い Image Optimization を production 環境で実現することを検討してください。Linux プラットフォームでは、sharp
はメモリ使用量を過度に増加させないように、追加の設定 を require する場合があります。- 最適化された画像の caching behavior of optimized images について詳しく学び、TTL の設定方法を学びましょう。
- 好みに応じて、
next/image
の他の利点を保持したまま、Image Optimization を無効にすることもできます。例えば、画像の最適化を自分で別々に行っている場合などです。
Middleware
Middleware は、next start
を使用したデプロイ時にゼロ設定で自己ホストする仕組みです。それは受信 request へのアクセスを必要とするため、静的な export を使用する場合にはサポートされません。
Middleware は、Node.jsAPI の一部である runtime を使用して低遅延を保証するため、アプリケーション内のすべての route またはアセットの前で実行される可能性があります。この runtime は at the edge での実行を require せず、単一地域の server で動作します。複数の地域で Middleware を実行するためには、追加の設定とインフラが必要です。
すべての Node.js API を必要とするロジック(または外部パッケージ)を追加することを検討している場合、このロジックを layout として、Server Component に移動することができるかもしれません。例えば、headers のチェックやリダイレクトなどが挙げられます。また、 headers 、 cookies 、または query パラメータを使用して、next.config.js
を経由して redirect や rewrite を行うこともできます。それが効果がない場合は、カスタム server も利用することができます。
Environment Variables
Next.js はビルド時とランタイムの環境変数の両方をサポートできます。
default では、環境変数はサーバー上でのみ利用可能です。環境変数をブラウザに公開するには、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:
- server 起動時に
register
function を使用してコードを実行することができます。- runtimeConfig オプションの使用は推奨しません。これはスタンドアロン出力モードでは動作しないためです。代わりに、App Router の段階的導入をお勧めします。
キャッシングと ISR
Next.js は、cache された Response、生成された静的ページ、build の出力、および画像、フォント、scripts などの他の静的アセットを扱うことができます。
ページのキャッシングと再検証( Incremental Static Regeneration ( ISR )または App Router の新機能を使用)は、同じ共有 cache を使用します。 default では、この cache は Next.js server のファイルシステム(ディスク)に保存されます。Pages と App Router を使用して自己ホスティングを行う際には、これが自動的に動作します。
あなたは、Next.js cache の位置を変更できます。これにより、キャッシュ済みのページやデータをずっと使えるストレージに保存したい場合や、あなたの Next.js アプリケーションの複数のコンテナまたはインスタンス間で cache を共有したい場合などに便利です。
自動キャッシング
- Next.js は、本当に不変なアセットに対して
Cache-Control
を header とし、public, max-age=31536000, immutable
を設定します。これは上書きできません。これらの不変なファイルにはファイル名に SHA ハッシュが含まれているため、無期限に安全にキャッシュできます。例えば、静的な Image のインポートです。画像の TTL を設定することができます。 - Incremental Static Regeneration ( ISR )は、
Cache-Control
の header にs-maxage: <revalidate in getStaticProps>, stale-while-revalidate
を設定します。この再検証時間は、あなたのgetStaticProps
functionで秒単位で定義されます。revalidate: false
を設定した場合、 default で一年間の cache 期間になります。 - 動的にレンダリングされたページは、ユーザー固有のデータがキャッシュされるのを防ぐために、
Cache-Control
header をprivate, no-cache, no-store, max-age=0, must-revalidate
に設定します。これは、App Router と Pages Router の両方に適用されます。これには、Draft Mode も含まれます。
静的アセット
もし別のドメインや CDN 上で host として静的アセットを利用したい場合、assetPrefix
configuration をnext.config.js
の中で使用することができます。 Next.js は、このアセットプレフィックスを JavaScript または CSS ファイルを取得するときに使用します。アセットを別のドメインに分けることは、DNS および TLS の解決に追加の時間がかかるというデメリットがあります。
キャッシングの設定
Default では、生成された cache アセットはメモリ(Default は 50MB)とディスクに保存されます。Kubernetes のような container オーケストレーションプラットフォームを使用して Next.js をホスティングする場合、各ポッドは cache のコピーを持っています。Default ではポッド間で cache が共有されていないため、stale なデータが表示されるのを防ぐために、Next.js cache を設定して cache handler を提供し、メモリ内キャッシングを無効にすることができます。
セルフホスティング時に ISR/Data の Cache の場所を設定するには、ご自身のnext.config.js
ファイルでカスタムの handler を設定できます:
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // disable default in-memory caching
}
次に、プロジェクトの root に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)
}
}
}
}
カスタムの cache handler を使用すると、Next.js アプリケーションをホストするすべてのポッド間で一貫性を確保することができます。例えば、Redis や AWS S3 のような場所にキャッシュした値を保存することができます。
Good to know:
revalidatePath
は、cache タグの上にある便利なレイヤーです。revalidatePath
を呼び出すと、提供されたページに対して特別な default タグを使用してrevalidateTag
関数が呼び出されます。
Build Cache
Next.js はnext build
の間に ID を生成し、どの version のアプリケーションが提供されているかを識別します。同じ build が複数のコンテナを起動するために使用されるべきです。
あなたが環境の各段階で再構築している場合、コンテナ間で使用する一貫した build ID を生成する必要があります。next.config.js
の中でgenerateBuildId
コマンドを使用してください。
module.exports = {
generateBuildId: async () => {
// This could be anything, using the latest git hash
return process.env.GIT_HASH
},
}
Version スキュー
Next.js は、ほとんどの version スキュー の問題を自動的に軽減し、新しいアセットが検出されたときにアプリケーションを自動的に再読み込みします。たとえば、build ID が一致しない場合、ページ間の遷移は、プリフェッチされた value を使用するのではなく、ハードなナビゲーションを実行します。
アプリケーションが再読み込みされると、ページ間のナビゲーションで維持されるように設計されていない場合、アプリケーションの状態が失われる可能性があります。たとえば、URL 状態やローカルストレージを使用すると、ページの refresh 後も状態が維持されます。しかし、useState
のような component の状態はそのようなナビゲーションで失われます。
Vercel は、新しい build が展開されている間に、前の build からのアセットと機能が依然として利用可能であることを確認するために、Next.js アプリケーションに追加の skew protection を提供します。
Manual Graceful Shutdowns
自己ホストする際には、SIGTERM
やSIGINT
シグナルで server がシャットダウンしたときに code を実行したいかもしれません。
あなたは env の variableNEXT_MANUAL_SIG_HANDLE
をtrue
に設定し、その後で_document.js
ファイル内でそのシグナルの handler を register することができます。package.json
スクリプト内で環境の variable を直接 register する必要があり、.env
ファイルの中ではないです。
Good to know: 手動でのシグナル処理は
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)
})
}