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知っておくと良いこと:
- プロジェクトが特定のポートまたはホスト名でリッスンする必要がある場合は、
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.config.jsが含まれるフォルダ (例: packages/web-app) である Next.js プロジェクトのルートを指し、必ずしもモノレポのルートではありません。
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/**/*'],
  },
}知っておくと良いこと:
- クロスプラットフォーム互換性のために、パターンではスラッシュ (
/) を優先して使用してください。- 大きすぎるトレースを避けるために、パターンはできるだけ狭くしてください (リポジトリのルートでの
**/*は避けてください)。
ネイティブ/ランタイムアセットの一般的なインクルードパターン
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
  },
}役に立ちましたか?