🔨
Next.jsのビルドプロセスに関するメモ
npm run dev
、npm run start
、npm run build
の違いがわからない
ある程度は把握してるが、実際のところ詳しく何がどうなってるのか知らなかったのでメモ書き
npm run dev
- Next.js の開発サーバーを起動し、開発モードでアプリケーションをコンパイルする
-
.next
ディレクトリに最適化されていないファイルが配置される - この開発モードでは、ソースコードの変更がリアルタイムで反映され、ホットリローディング(ファイルを保存すると自動的にページが更新される機能)が有効になる
- ソースマップが生成され、デバッグが容易になる
- コンパイル速度は最適化されていないため、本番モードより重め
- エラー表示や警告が詳細に表示され、開発者が問題を迅速に特定できるように設計されている
npm run build
- Next.js アプリケーションを本番用にビルドする
- アプリケーションのすべてのページとコンポーネントがコンパイルされ、最適化された静的ファイルとサーバーサイドのスクリプトが .next ディレクトリに生成される
- このプロセスには、コードの圧縮、不要なコードの削除(ツリーシェイキング)、画像最適化、CSSの最適化などが含まれる
- 生成されるファイルはパフォーマンスが最適化されており、ロード時間が短縮される
- ビルド後のアウトプットは本番環境で使用するために設計されている
- SSR(サーバーサイドレンダリング)や静的サイト生成(SSG)の設定に基づいて、事前レンダリングが行われる
- このプロセスには、コードの圧縮、不要なコードの削除(ツリーシェイキング)、画像最適化、CSSの最適化などが含まれる
npm run start
-
npm run build
で生成されたビルドを本番環境で実行する - Next.js サーバーが起動し、ビルドされたアプリケーションをサーブする
- このコマンドは、ビルドプロセスを経て生成されたアウトプットを本番環境でテストする際や、実際にデプロイする際に使用する
- 高速で安定したパフォーマンス
- 開発モードとは異なり、リアルタイムのコード変更やホットリローディングは行われない
- セキュリティとパフォーマンスが最適化された状態で稼働する
.next
フォルダって何?
- Next.jsで
npm run dev
やnpm run build
を実行すると、.next
ディレクトリが生成される
server
- 主にサーバーサイドで実行されるファイル
server/app
- アプリケーションのサーバーサイドの全般的なロジックと設定
- 特にNext.jsのアプリケーションでグローバルな設定や共通機能が定義された場合、その実装の多くはここにコンパイルされる
-
_app.tsx
とか、共通ロジックのヘルパーとかクライアントとか...
-
- アプリケーションの起動時やリクエスト処理時に基本となる機能を提供し、ページ固有のロジックと区別されるアプリケーション全体にわたる機能をサポートする
server/pages
- appとは違い、個々のページ固有の処理が対象
- ページコンポーネントのサーバーサイドレンダリング(SSR)に必要なコードや、静的サイト生成(SSG)で事前に生成されるページのデータ取得ロジックがここに格納される
- 動的ルート(例えば pages/[id].tsx)に対応するファイルも含まれることがある
- ユーザーからのリクエストに基づき、個々のページを適切にレンダリングするためのサーバーサイドのコードを実行する
- HTMLとして事前レンダリングされるページや、APIルートのハンドラが含まれる
server/chunks
- 依存関係やライブラリ、フレームワーク自体のコードなど、ページ間で共有されるコードの断片(チャンク)が含まれる
そもそもchunk
ってどういう概念?
JavaScriptの歴史から紐解いていこう
- ページにベタ書き時代
- JavaScriptは小規模でシンプルなスクリプトをページに直接埋め込む形で利用されていた
- ページごとにスクリプトが書かれ、大きな依存関係はほとんどなかった
- ライブラリやフレームワークの時代
- jQueryやAngularJS、ReactなどのJavaScriptライブラリやフレームワークが登場
- 「Aライブラリを使うならBライブラリも必要」 のように、依存関係で複雑化
- モジュールバンドラーの時代
- コードの依存関係を管理し、ブラウザが解釈できる形式に変換するために、WebpackやBrowserifyといったモジュールバンドラーが登場
- 開発者はモジュール(小さなコード片)を独立して書くことができ、最終的にバンドラーがこれらを一つのファイルにまとめ上げる役割を担うようになった
- 全部1ファイルにまとめる関係上、クソデカJavaScriptファイルが生成されるようにもなった
- パフォーマンスを考慮してクソデカJavaScriptを分割(
chunk
)する時代- モジュールバンドラーによって生成されるクソデカコードの断片を
chunk
と呼ぶ - 大きなアプリケーションの場合、バンドルされたクソデカファイルの初期ロードが長すぎてつらい...
- これを解決するため、効率的にロード方法としてコードを複数に分割するようになった
- 遅延ロード
- ユーザーが実際に必要とする時にのみ特定の機能やページのコードをロードさせる
- キャッシュ最適化
- 変更のないチャンクはブラウザにキャッシュされ続ける
- ので、ユーザーは変更のあった必要な差分だけロードすればOKになる
- 並行ロード
- 複数の小さなファイル(チャンク)としてコードが提供される
- 並行ダウンロードによって、ページのパフォーマンスが向上する
- 遅延ロード
- モジュールバンドラーによって生成されるクソデカコードの断片を
server/middleware
- ページまたはAPIルートの前に実行されるカスタムサーバーサイドロジックが格納される
static
- 主にクライアントサイドサイドで実行されるファイル
static/chunks
- アプリケーションの構成要素を小さなパーツに分割したJavaScriptファイル
- 必要なコードのみをクライアントに送信することができ、パフォーマンスが向上する
static/css
- ビルドプロセス中に生成されたCSSファイル
- サーバーサイドで生成されたスタイルシートや、クライアントサイドで動的にロードされるスタイルシート
- TailwindCSSのJITモードで生成されたスタイル(例:
mt-[16px]
)なども含まれる
types
- 各ページコンポーネントで参照される型定義ファイル
app-build-manifest.json
- Next.js のビルドプロセス中に生成されるファイルの一つ
- 主にクライアントサイドに関する情報が含まれている
- アプリケーションのビルド情報を含むJSON形式のマニフェストファイル
- ビルドされたページやロードされるリソースに関する重要なデータを含む
- ページの対応: 各ページに対してどのJavaScriptおよびCSSファイルが必要か、そのマッピングが記載されている
- ロードの優先順位: どのリソースが優先的にロードされるべきか、その情報が含まれる
- ダイナミックインポート: ページやコンポーネントでダイナミックにインポートされるモジュールのリストが記載されている
そもそもマニフェストファイルって何?
- アプリケーションやソフトウェアの構成、機能、ビルドプロセスに必要な情報を定義するファイルのこと
- アプリケーションがどのように動作するか、どのリソースを使用するか、またどのようにビルドされるかなど、重要なメタデータを含んでいる
マニフェストファイルは通常、テキストベースのフォーマット(JSON、XMLなど)で書かれており、アプリケーションのデプロイや実行に必要な指示や設定が記載されています。様々な用途で使われるいくつかの一般的なマニフェストファイルの例は以下の通り
build-manifest.json
- ビルド時のキャッシュファイルが含まれる
- これにより、連続するビルドが以前の計算結果を再利用でき、ビルド時間が短縮される
- 主にアプリケーション全体で必要な定義などが記載されている
react-loadable-manifest.json
- 以前の Next.jsバージョンや、React Loadableというライブラリを使用しているプロジェクトで見られるファイル
- React Loadableは、Reactコンポーネントを動的にロードするための高階コンポーネントを提供するライブラリ
- このライブラリの目的は、コード分割と非同期コンポーネントのローディングを簡単にすることで、初期ロード時のJavaScriptのサイズを削減し、パフォーマンスを向上させる
Discussion