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 は、本番デプロイに必要なファイルのみをコピーする standalone フォルダを自動的に作成できます。これには node_modules の選択されたファイルも含まれます。
この自動コピーを利用するには、next.config.js で有効にできます。
module.exports = {
  output: 'standalone',
}これにより .next/standalone にフォルダが作成され、node_modules をインストールせずに単独でデプロイできます。
さらに、最小限の server.js ファイルも出力されます。これは next start の代わりに利用できます。この最小限のサーバーは、デフォルトでは 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知っておくと良いこと:
next.config.jsはnext build中に読み込まれ、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 = {
  // this includes files from the monorepo base two directories up
  outputFileTracingRoot: path.join(__dirname, '../../'),
}- Next.js が必要なファイルをインクルードできなかったり、不要なファイルを誤ってインクルードしたりする場合があります。そのような場合は、next.config.jsでoutputFileTracingExcludesおよびoutputFileTracingIncludesを利用できます。各オプションは、キーが **ルートグロブ**(ルートパスに対して picomatch でマッチされます。例:/api/hello)であり、値がプロジェクトルートから解決される **グロブパターン** で、トレースに含めるか除外するファイルを指定します。
知っておくと便利: モノレポでは、
project rootは 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 と include を組み合わせて使用します。
const path = require('path')
 
module.exports = {
  // Trace from the monorepo root
  outputFileTracingRoot: path.join(__dirname, '../../'),
  outputFileTracingIncludes: {
    '/route1': ['../shared/assets/**/*'],
  },
}知っておくと良いこと:
- クロスプラットフォーム互換性のために、パターンではフォワードスラッシュ(
/)を優先してください。- 大きすぎるトレースを避けるために、パターンはできるだけ狭くしてください(リポジトリのルートでの
**/*は避けてください)。
ネイティブ/ランタイムアセットの一般的な include パターン
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
  },
}役に立ちましたか?