next buildを--inspect オプションでプロファイリングする

Node.jsのパフォーマンスをChromeの開発者ツールでプロファイリングするで、nodeコマンドに--inspectオプションを付けて実行することで、Node.jsのプロファイルをChrome DevToolsで確認できることを説明した。
しかし、同様にNext.jsアプリのビルドをプロファイリングしようとすると、ビルド中に呼ばれているはずの関数呼び出しを確認できない。

原因

Next.jsをWebpackを使ってビルドする場合、ビルド中に子プロセスを起動している。
これはメモリ使用量を削減するために設計された仕組みで、Webpack Build Workerと呼ばれている。
このときinspect関連のオプションを明示的に除去している。
そのため--inspectオプションを付けてNext.jsアプリをビルドしても、子プロセスには引き継がれず、プロファイリングできない。

utils.ts
export function getParsedNodeOptionsWithoutInspect() {
  const args = getNodeOptionsArgs()
  if (args.length === 0) return {}

  const parsed = parseNodeArgs(args)

  // Remove inspect options.
  delete parsed.inspect
  delete parsed['inspect-brk']
  delete parsed['inspect_brk']

  return parsed
}

上記のコードは、utils.ts#L216-L228 より引用している。

解決方法

Next.jsの設定ファイルで、Webpack Build Workerを無効化する。
具体的には、next.config.jswebpackBuildWorker: falseを設定する。

next.config.js
module.exports = {
  experimental: {
    webpackBuildWorker: false
  }
}

この状態で以下のコマンドを実行すると、デバッグを行うWebSocketのエンドポイントが発行される。

NODE_OPTIONS='--inspect' node node_modules/next/dist/bin/next build

Debugger listening on ws://127.0.0.1:9229/2684d1ef-fea3-41f5-8884-b48e2a58bbb9
For help, see: https://nodejs.org/en/docs/inspector

Chromeで「chrome://inspect/」にアクセスすると、デバッグ可能なNode.jsのプロセスが表示される。 スクリーンショット:chrome://inspect/の画面を表示している

[inspect]をクリックすると、Chrome DevToolsの[Performance]タブが表示される。
あとはRecordを実施すると、Next.jsのビルド処理をプロファイリングできる。 スクリーンショット:Chrome DevToolsのPerformanceタブでNext.jsのビルド処理をプロファイリングしている

注意点

Webpack Build Workerを無効化すると、すべてのビルド処理がメインプロセスで実行されるため、メモリ使用量が増加する。
また、並列に処理できなくなるため、ビルドパフォーマンスに影響する可能性がある。