コンテンツにスキップ

output

ビルド時、Next.js は各ページとその依存関係を自動的にトレースし、アプリケーションのプロダクションバージョンのデプロイに必要なすべてのファイルを特定します。

この機能は、デプロイメントのサイズを劇的に削減します。以前は、Docker でデプロイする場合、next start を実行するためにパッケージの dependencies にあるすべてのファイルをインストールする必要がありました。Next.js 12 以降では、.next/ ディレクトリの Output File Tracing を利用して、必要なファイルのみを含めることができます。

さらに、これにより、さまざまな問題を引き起こし、不要な重複も発生させる非推奨の serverless ターゲットが不要になります。

仕組み

next build の実行中、Next.js は @vercel/nft を使用して、importrequirefs の使用状況を静的に分析し、ページがロードする可能性のあるすべてのファイルを特定します。

Next.js のプロダクションサーバーも、必要なファイルのトレースを行い、.next/next-server.js.nft.json に出力します。これはプロダクションで活用できます。

.next 出力ディレクトリにエミットされた .nft.json ファイルを活用するには、各トレース内のファイルリストを .nft.json ファイルからの相対パスで読み込み、それらをデプロイメント場所にコピーできます。

トレースされたファイルの自動コピー

Next.js は、プロダクションデプロイに必要なファイルのみをコピーする standalone フォルダを自動的に作成できます。これには node_modules の一部のファイルも含まれます。

この自動コピーを利用するには、next.config.js で有効にできます。

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.jsoutputFileTracingRoot を設定できます。
packages/web-app/next.config.js
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 プロジェクトのルートを指し、必ずしもモノレポのルートではありません。

next.config.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/ 配下のパスを参照できます。
next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/products/*': ['src/lib/payments/**/*'],
    '/*': ['src/config/runtime/**/*.json'],
  },
  outputFileTracingExcludes: {
    '/api/*': ['src/temp/**/*', 'public/large-logs/**/*'],
  },
}

'/*' のようなグローバルキーを使用して、すべてのルートを対象にすることもできます。

next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['src/i18n/locales/**/*.json'],
  },
}

これらのオプションはサーバーのトレースに適用され、サーバーのトレースファイルを生成しないルートには影響しません。

  • Edge Runtime ルートは影響を受けません。
  • 完全に静的なページは影響を受けません。

モノレポや、アプリフォルダ外のファイルを含める必要がある場合は、outputFileTracingRoot と include を組み合わせて使用します。

next.config.js
const path = require('path')
 
module.exports = {
  // Trace from the monorepo root
  outputFileTracingRoot: path.join(__dirname, '../../'),
  outputFileTracingIncludes: {
    '/route1': ['../shared/assets/**/*'],
  },
}

知っておくと良いこと:

  • クロスプラットフォーム互換性のために、パターンではスラッシュ (/) を優先して使用してください。
  • 大きすぎるトレースを避けるために、パターンはできるだけ狭くしてください (リポジトリのルートでの **/* は避けてください)。

ネイティブ/ランタイムアセットの一般的なインクルードパターン

next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
  },
}