Next.jsで実現するAPIリクエスト設計:React直リクエスト vs API Routeの比較
APIリクエストの設計パターンの疑問
Next.jsからAPIをリクエストする設計パターンとして、以下の2パターンがあることを前回の記事に書いた
- Reactコンポーネントから直接リクエストする
- API Routeを経由してリクエストする
それぞれのメリット・デメリットもまとめたが、疑問が残り少し深掘りした
API Routeを利用するメリット
- リクエストヘッダに含まれるトークン等の機密情報を隠蔽できるためセキュリティが向上する
- すべてのAPI呼び出しがNext.js側に集約されるためリクエストログを一元管理できる
- 将来バックエンドのエンドポイント構成が変わっても、Next.js側のAPIルートを調整するだけでフロントの実装変更を最小限に抑えられる
- SEO対策や高速表示が可能となる
API Routeを利用するデメリット
フロント→Next API→Railsという余分なネットワーク経路が増えるぶん遅延が大きくなり、Vercel等のサーバーレス環境では呼び出しごとのコストも増える
Reactコンポーネントからリクエストする方法を選んだ場合、Next.jstの恩恵として何が残るのか?
- ファイルベースのルーティングReact→react-routerなどのを利用し、ルート定義の設定が必要となるNext.js→ページファイルの設置だけで自動的にルーティングが構成される
- 自動コード分割とパフォーマンス最適化React→React.lazyやSuspenseを利用して分割は可能だが、設定や運用は手動で行うNext.js→ページごとに自動でコード分割が行われ、最適化もフレームワーク側で自動管理される
- デプロイの運用の容易さReact→デプロイ先の環境設定やビルド後の最適化を設定する必要があるNext.js→Vercelなどとの連携が協力で、デプロイからスケーリングまでの運用がシンプルに行える
React単体でもこれらの機能を外部ライブラリやツールを組み合わせることで実現可能だが、Next.jsはそれらを統合した包括的なフレームワークとして提供しているため、初期設定や運用の手間が大幅に軽減されるのが大きなメリットとなっていそうである直接Rails APIへのリクエストなど、シンプルな用途だけであればReactでも十分だが、将来的な拡張性や開発体験、デプロイの容易さを考慮すると、Next.jsを採用する理由は十分あるのかもしれない
Next.jsで、ページごとに自動でコード分割が行われ、最適化もフレームワーク側で自動管理されるプロセス
Next.jsでは、ビルド時に各ページのエントリーポイントを検出し、各ページごとに必要なコードのみを含むバンドル(チャンク)を自動生成する仕組みになっており、以下のようなプロセスが行われている
-
ページごとのエントリーポイント
Next.jsは、/pageディレクトリ内の格ファイルを個別のエントリーポイントとみなし、そのふぁいるでしようされるコンポーネントやライブラリだけをJavaScriptファイル(バンドル)を生成するこれにより、ユーザーがあるページを訪問する際、そのページに必要なコードだけがロードされ、不要なコードは読み込まれないようになっている -
共通モジュールの分離
ページ間で共通して使用されるライブラリ(React自体やその他の共通モジュール)は、共通チャンクとして分離され、キャッシュが有効になるこれにより、複数ページ間で共通部分が再利用され、初回ロードのサイズが削減される -
プリフェッチと動的インポート
Next.jsの<Link>コンポーネントは、ユーザーがリンクにホバーしたり画面上に表示されると、そのリンク先ページのコードをバックグラウンドでプリフェッチ(事前取得)するまた、next/dynamicを使った動的インポートにより、ページ内の大きなコンポーネントや特定の機能を必要なタイミングで遅延読み込みすることが可能である -
Webpackによる自動最適化
Next.jsは内部でWebpackを利用しており、ビルド時にTree Shaking(未使用コードの除去)や圧縮、バンドルサイズの最適化などを自動的に実施するこれにより、最終的に配信されるJavaScriptファイルは必要最小限のコードだけになっている
このように、Next.jsはフレームワーク側でルーティングやファイル構造を解析し、自動的に最適な形で各ページのコードを分割・管理することで、ユーザーにとっての初期ロード速度の向上や、ページ遷移時のスムーズな体験を実現している
Reactの場合は?
-
バンドルの生成とコード分割
Create React App(CRA)などを使うと、通常はアプリ全体が1つまたは数個の大きなバンドルにまとめられるこれは、Next.jsが/pageディレクトリ内の格ファイルごとに個別のバンドルを自動生成するのと対照的である※主導のでコードの分割をすることは可能である -
ルーティング
純粋なReactの場合、ルーティングは通常 react-router や reach-router といったライブラリを使って設定しするが、ファイル構成に基づく自動ルーティングではなく、手動でルートの定義を書く必要がある -
最適化
Webpackなどのバンドラーが提供する最適化(Tree Shaking、ミニファイ、圧縮など)はCRAでも利用できるが、Next.jsのようなページ単位の自動コード分割、プリフェッチ、共通チャンクの自動抽出などは、設定や追加ライブラリを用いて自前で実装する必要がある
結論
Next.js:
ファイルベースのルーティングを利用して、ビルド時に各ページごとのエントリーポイントを自動検出し、コード分割やプリフェッチ、共通チャンクの管理などが自動的に行われるため、開発者は特別な設定をせずに高いパフォーマンスを享受できる
純粋なReact:
基本的には単一のエントリーポイントからのバンドル生成となるため、自動的なページ単位のコード分割は行われず、必要な場合はReact.lazyやSuspense、あるいは他のコード分割ライブラリ(たとえばreact-loadable)などを利用して手動で実装する必要がある
Discussion