output
ビルド中に、Next.jsは各ページとその依存関係を自動的にトレースして、アプリケーションのプロダクション版のデプロイに必要なすべてのファイルを特定します。
この機能はデプロイメントのサイズを大幅に削減するのに役立ちます。以前は、Dockerでデプロイする際にnext startを実行するために、パッケージのdependencies内のすべてのファイルをインストールする必要がありました。Next.js 12以降は、.next/ディレクトリのOutput File Tracingを活用して、必要なファイルのみを含めることができます。
さらに、これにより非推奨のserverlessターゲットの必要性が排除され、様々な問題を回避し、不要な重複を解消します。
動作仕組み
next build実行中に、Next.jsは@vercel/nftを使用してimport、require、およびfsの使用状況を静的に解析し、ページが読み込む可能性のあるすべてのファイルを特定します。
Next.jsのプロダクションサーバーも必要なファイルについてトレースされ、.next/next-server.js.nft.jsonに出力されます。これはプロダクション環境で活用できます。
.next出力ディレクトリに出力された.nft.jsonファイルを活用するには、各トレース内のファイルリストを.nft.jsonファイルを基準として読み込み、デプロイ先にコピーします。
トレースされたファイルの自動コピー
Next.jsは、node_modules内の選択されたファイルを含む、プロダクションデプロイメントに必要なファイルのみをコピーするstandaloneフォルダを自動的に作成できます。
この自動コピーを活用するには、next.config.jsで有効にします:
module.exports = {
output: 'standalone',
}これにより、.next/standaloneフォルダが作成され、node_modulesをインストールせずにそのままデプロイできます。
さらに、next startの代わりに使用できる最小限のserver.jsファイルも出力されます。この最小限のサーバーは、デフォルトではpublicまたは.next/staticフォルダをコピーしません。これらはCDNで処理するのが理想的ですが、これらのフォルダを手動でstandalone/publicとstandalone/.next/staticフォルダにコピーした後、server.jsファイルが自動的にこれらを提供します。
これらを手動でコピーするには、next build後にcpコマンドラインツールを使用できます:
cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/最小限のserver.jsファイルをローカルで起動するには、以下のコマンドを実行します:
node .next/standalone/server.js補足:
- プロジェクトが特定のポートまたはホスト名でリッスンする必要がある場合、
server.jsを実行する前にPORTまたはHOSTNAME環境変数を定義できます。例えば、PORT=8080 HOSTNAME=0.0.0.0 node server.jsを実行してhttp://0.0.0.0:8080でサーバーを起動します。
注意事項
- モノレポのセットアップでのトレース中は、プロジェクトディレクトリがデフォルトではトレースのルートとして使用されます。
next build packages/web-appの場合、packages/web-appがトレースのルートとなり、そのフォルダ外のファイルは含まれません。このフォルダ外のファイルを含めるには、next.config.jsでoutputFileTracingRootを設定できます。
const path = require('path')
module.exports = {
// これはモノレポベースから2つ上のディレクトリからのファイルを含めます
outputFileTracingRoot: path.join(__dirname, '../../'),
}- Next.jsが必要なファイルを含めるのに失敗したり、不要なファイルを誤って含めたりする場合があります。そのような場合、
next.config.jsでoutputFileTracingExcludesおよびoutputFileTracingIncludesをそれぞれ活用できます。各オプションは、ルートグロブ(ルートパス(例:/api/hello)に対してpicomatchと一致)をキーとし、トレースに含めるまたは除外するファイルを指定するプロジェクトルートから解決されたグロブパターンを値とするオブジェクトを受け入れます。
補足: モノレポでは、
プロジェクトルートはNext.jsプロジェクトルート(next.config.jsを含むフォルダ。例:packages/web-app)を指し、必ずしもモノレポルートではありません。
module.exports = {
outputFileTracingExcludes: {
'/api/hello': ['./un-necessary-folder/**/*'],
},
outputFileTracingIncludes: {
'/api/another': ['./necessary-folder/**/*'],
'/api/login/\\[\\[\\.\\.\\.slug\\]\\]': [
'./node_modules/aws-crt/dist/bin/**/*',
],
},
}src/ディレクトリの使用はこれらのオプションの記述方法に影響しません:
- キーはルートパス(
'/api/hello'、'/products/[id]'など)と一致します。 - 値はプロジェクトルートを基準として解決されるため、
src/の下のパスを参照できます。
module.exports = {
outputFileTracingIncludes: {
'/products/*': ['src/lib/payments/**/*'],
'/*': ['src/config/runtime/**/*.json'],
},
outputFileTracingExcludes: {
'/api/*': ['src/temp/**/*', 'public/large-logs/**/*'],
},
}'/*'のようなグローバルキーを使用してすべてのルートをターゲットにすることもできます:
module.exports = {
outputFileTracingIncludes: {
'/*': ['src/i18n/locales/**/*.json'],
},
}これらのオプションはサーバートレースに適用され、サーバートレースファイルを生成しないルートには影響しません:
- Edge Runtimeルートは影響を受けません。
- 完全にスタティックなページは影響を受けません。
モノレポ内、またはアプリフォルダ外のファイルを含める必要がある場合、outputFileTracingRootとincludesを組み合わせます:
const path = require('path')
module.exports = {
// モノレポルートからトレース
outputFileTracingRoot: path.join(__dirname, '../../'),
outputFileTracingIncludes: {
'/route1': ['../shared/assets/**/*'],
},
}補足:
- クロスプラットフォーム互換性のため、パターンではスラッシュ(
/)を使用してください。- パターンをできるだけ狭くして、トレースのサイズが大きくなるのを避けてください(リポジトリルートで
**/*を避けます)。
ネイティブ/ランタイムアセットの一般的なincludeパターン:
module.exports = {
outputFileTracingIncludes: {
'/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
},
}