1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js(App Router)が誕生するまでを整理してみた

Last updated at Posted at 2025-06-12

背景

最近、会社でNext.jsのApp Routerを用いた開発をしており、アーキテクチャやら設計やら実装やら携わらせてもらっています。

仕事をしていて、私は常々

🐶『Next.jsをさらに深く理解したいなぁ〜』

と思っておりました。


そんな時にふと立ち寄った本屋にて、何やら私の目を引く書籍がありました。

🐶『ん?なんだこれは?』


私は本に歩み寄り、その本を手に取ったのです。

それが「実践Next.js—⁠—App Routerで進化するWebアプリ開発」という書籍との出会いです。

🐶『Next.jsが体系的に学べそうな一冊じゃあないかッッ!!!』

つい口に出してしまいました。(※出してません)


私は寝る間も惜しんで本書を読んで、自分でもいろいろ調べてみて「Next.jsのApp Routerを使うなら覚えておきたいやつをまとめちゃえ」ってなりました。

ってなわけでAIさんの力を借りながら色々調べてまとめたんで、みなさま見ていただけますと幸いでございます。

Next.js App Router誕生までをざっくりと

🐶「Next.jsが生まれるまでの背景って?」

初めにですが、「そもそもNext.jsってなんで生まれたの?」っていう話をしようかと思います。

今までのフロントエンド開発は以下のような悩みがありました。

  • SPA(Single Page Application) : 👦『画面遷移早いけど、初回ロードが遅い…!』
  • SSR(Server-Side Rendering) : 🧑『SEOはいいなぁ〜!でも、サーバー負荷がなぁ〜』
  • SSG(Static Site Generation) : 👴『CDNで爆速配信できてええの〜。ただぁ〜!ん〜、更新のラグ長いのぉ〜!?』
🐶「SPA, SSR, SSGってなに?」

🐶: 「ねえねえおじいちゃん! ぼく最近“SPA”とか“SSR”とか“SSG”って言葉を聞いたワン! いったい何の呪文なの? 教えてよ〜!」

👴: 「おお、イッヌや。焦らず聞くんじゃぞ。まず“SPA”は “Single Page Application” の略じゃ。ページが一枚だけあって、あとは中身だけを JavaScript で差し替えていく仕組みなんじゃ。」

🐶: 「へえ! ページをめくるんじゃなくて、中身だけ入れ替えるってこと? じゃあロードが速いの?」

👴: 「初回に必要な JavaScript をどっさり持ってくるから最初は少しかかるが、二回目以降は画面遷移がぬるぬる動くんじゃ。ゲームみたいに軽快になるのが売りじゃな。」

🐶: 「なるほど! じゃあ“SSR”ってのはどうなの? “スーパー・スーパードッグ・ラン”とか?🐾」

👴: 「はっはっは、イッヌは陽気じゃのう。“SSR” は “Server-Side Rendering” のことじゃ。ページを開くたびに“サーバー”が HTML を組み立てて送り返してくれる。だから検索エンジンにも優しいし、初表示が速い。」

🐶: 「へえ〜! サーバーのおじさんが毎回お弁当を作って持ってきてくれる感じ?」

👴: 「まさにそれじゃ。お弁当(HTML)を温かいうちに渡してくれるから、食べる(表示する)のが早いんじゃ。ただし毎回作るから、たくさん注文がくると厨房が大忙しになるんじゃな。」

🐶: 「わかるワン! じゃあ最後の“SSG”ってやつは?」

👴: 「“Static Site Generation” の略じゃ。これはあらかじめ全部のページを冷凍食品のように作り置きしておく方法じゃ。ビルドのときに HTML を生成しておき、配るときはただ出すだけだから超速い。」

🐶: 「えっ、じゃあレンチンしてすぐ食べられる冷凍チャーハンみたいなもの?!」

👴: 「そうそう。配るだけだから速いが、作り置きなので中身を変えたいときはまた全部作り直す手間があるんじゃ。」

🐶: 「まとめると──

  • SPA: 最初に材料を全部持ってきて、あとは台所(ブラウザ)で調理し続ける!
  • SSR: 注文が入るたびにシェフ(サーバー)が作りたてを届ける!
  • SSG: 前日に大量に作り置きして、食べるときはチンしてすぐ!
    って感じ? イッヌでもわかったワン!✨」

👴: 「その通りじゃ。最近のフレームワーク(Next.js や Nuxt など)は SPA・SSR・SSG を組み合わせて使えるから、用途に合わせて料理法を選ぶとよいぞい。」

🐶: 「ありがとうおじいちゃん! これでウェブ開発もモリモリ頑張れるワン!🐾」

👴: 「うむ、イッヌよ。分からぬことがあったらまた聞きに来るんじゃぞ。わしはいつでもここで茶をすすっておるからのう。」

そんなときに2016年にNext.js (Pages Router)が登場しました。

Next.js Pages Routerはページ単位でSSRとSSGを切り替えることができるハイブリッド戦略を提案します。


Next.js Pages Routerの革新的なところは以下の部分にあります。

  • ページ単位でSSG・SSRを切り替えることができるハイブリッド戦略
  • ファイルベースでルーティングができるシンプルな仕組み

これにより開発者はサーバー負荷を軽減しつつ、初回ロードの速度最適化をほぼ意識することなく得られるようになりました。

🐶「Pages Routerってなにがすごかったの?」

🐶: 「おじいちゃん! React でサイトを作ると大変って聞くけど、Next.js の Pages Router が悩みを解決してくれるって本当? 詳しく知りたいワン!」

👴: 「よしイッヌ、昔のフロントエンドでみんながどんな壁にぶつかっていたか、それと Pages Router がどう救ってくれたかを順に見ていこうか。」


🚧 フロントエンド開発の主な悩み

👴: 「まずは困りごとを整理じゃ。

  1. ルーティング地獄 — ページが増えるたびに手書き設定が肥大化。
  2. 巨大バンドル — 初回ロードが遅く、コード分割を自前で書くのは骨が折れた。
  3. SEO の弱さ — クローラーが JS を解釈できず検索順位が伸びにくい。
  4. SSR/SSG の実装コスト — Node サーバーやビルド設定を一から構築。
  5. API との分離 — ちょっとしたバックエンドでも別リポジトリ&別デプロイ。
  6. 開発者体験(DX)の不足 — ホットリロードや型チェックを手動で整える必要があった。」

🐶: 「なるほど! 作る人も走らされてばっかりだったんだね。」


🌟 Pages Router がもたらした解決策

👴: 「ここからが逆転の一手じゃ。

  1. ファイルシステムベースのルーティング
    pages/about.js を置けば /about に自動マッピング。設定ファイルいらずで迷路を脱出。

  2. 自動コード分割+プリフェッチ
    ページ単位で JS を分割し、リンクが視界に入ると先読み。初回は軽く、遷移はぬるぬる。

  3. 組み込み SSR / SSG / ISR

    • getServerSideProps で毎リクエスト SSR。
    • getStaticProps + getStaticPaths でビルド時 SSG。
    • revalidate で ISR(静的再生成)。
      ページごとに切り替えられ、SEO と表示速度を状況に応じて最適化。
  4. API Routes の同居
    pages/api/hello.js/api/hello。フロントと軽量バックエンドが同じリポジトリ・同一デプロイになり、CORS やインフラの手間が激減。

  5. DX の底上げ
    保存即リロード、型チェック、詳細なエラーページ、国際化などを公式が面倒見。開発者は UI とビジネスロジックに集中できるんじゃ。」

🐶: 「おおー! 昔の悩みが一気に片づいた感じだワン! つまり――

  • 置くだけでルート完成🗂️
  • 自動分割で速い✂️
  • SSR/SSG/ISR を好きに選択⚡️
  • API も一緒🔌
  • 開発が快適🛠️

ってことだね!」

👴: 「その通りじゃ、イッヌ。Pages Router は“ページを作ればルートも最適化もついてくる”便利箱じゃ。これを活かして、もっと面白いサイトを作るとよいぞ。」

🐶: 「ありがとうおじいちゃん! これでボクも迷わず開発できるワン!」

🐶「Pages Routerでも悩みがあったの?」

フロントエンド開発のブレイクスルーとなったNext.js Pages Routerでしたが、課題もありました。

だいたいこんな感じです。

  1. 粒度がページ単位で固定
    データ取得やキャッシュ、レイアウトもページ単位でしか設定することができず、効率が悪かった
    データを渡す時もバケツリレーPropsでしかできず、深いツリーになると渡すデータが増えていくという課題があった
    await fetch()を使ってのデータフェッチは可能だったのだが、最適化が行われれおらず、型共有が煩雑だったり…

    (原文)With the Pages Router, layouts were not able to be composed, and data fetching could not be colocated with the component. With the new App Router, this is now supported.

    (日本語訳)Pages Routerでは、レイアウトを構成できず、データ取得をコンポーネントと同じ場所に配置することができませんでした。新しいApp Routerでは、これがサポートされるようになりました。

    参考:https://nextjs.org/blog/next-13-4#zero-setup-use-the-filesystem-as-an-api

  2. サーバー or クライアントの2択しか選べない
    SSRでは毎回すべてのHTMLを生成し、フロントエンドに送信する
    また、サーバーでしか使わないJSを切り離すことができず、JSバンドルが必ず送信されていた
    そのためフルハイドレーション(サーバーから送られてきたHTMLにJSをくっつけるプロセス)が行われており、効率が悪かった

    (原文)Previously, opt-ing into server-side rendering with Next.js (through getServerSideProps) meant that interacting with your application was blocked until the entire page was hydrated. With the App Router, we've refactored the architecture to be deeply integrated with React Suspense, meaning we can selectively hydrate parts of the page, without blocking other components in the UI from being interactive. Content can be instantly streamed from the server, improving the perceived loading performance of a page.

    (日本語訳)以前は、Next.js によるサーバーサイドレンダリング( 経由)を選択すると、getServerSidePropsページ全体がハイドレートされるまでアプリケーションとのインタラクションがブロックされていました。App Router では、アーキテクチャをリファクタリングし、React Suspense と深く統合しました。これにより、UI 内の他のコンポーネントの操作を妨げることなく、ページの一部を選択的にハイドレートできるようになりました。コンテンツはサーバーから瞬時にストリーミングされるため、ページの読み込みパフォーマンスが向上します。

    参考:https://nextjs.org/blog/next-13-4#zero-setup-use-the-filesystem-as-an-api

などです。

まぁ、要するに「粒度が荒いので最適化しずらい」のと「データはバケツリレーなので、ネストが深くなると渡すデータが増える」というのが課題だったということですね。

🐶「Pages Routerではどんな悩みがあったの?」

🐶: 「おじいちゃん! Pages Router が便利なのはわかったけど、“弱点”もちゃんと知りたいワン。どこがモヤッとしてたの?」

👴: 「うむ、イッヌ。Pages Router は当時のフロントエンドを救ったが、使い続けるうちにいくつか息苦しさが見えてきたんじゃ。大きく四つほど語ろうか。」


🪣 1) ページ単位の“バケツ”設計が粗い
👴: 「getServerSidePropsgetStaticPropsページごとに一個しか置けず、コンポーネントごとの細やかな取得ができん。

  • 一覧と詳細で同じ API を呼ぶときでも、ページ丸ごと再フェッチ。
  • 取ったデータは props で子・孫へ“手渡しリレー”。階層が深いほどコードが水やりホースみたいに伸びる。
  • キャッシュの単位もページ丸ごとだから、小さな更新でも全部作り直し。
    結果として“ほんの一口の水”を飲むのに “バケツごと” 運ぶような非効率さが残ったんじゃ。」

⚖️ 2) 「サーバー全部」か「ブラウザ全部」かの二択
👴: 「Pages Router は基本“SSR か CSR か”のスイッチしかない。

  • SSR にすると毎回サーバーで HTML を焼き直すので負荷が大きい。
  • しかもサーバー専用ロジックを切り離せず、クライアント用 JS が必ず一緒に届く。
  • 結果、HTML を受け取ったあとページ全体を React が再起動(フルハイドレーション)。静的な部分まで JS が走って重たい。
    『もっと静かな所はそのまま表示、動く所だけ React』といった部分的ハイドレーションができず、性能チューニングの自由度が低かったんじゃ。」

🔀 3) ネストしたレイアウトが組みにくい
👴: 「複数ページ間で共通するヘッダーやサイドバーを持たせたいとき、Pages Router では _app.js か各ページ内で包み込むしか手がなかった。

  • ルート階層が深くなると、どこまでが共通でどこからが個別かが曖昧になり、状態管理やスタイルの“ねじれ”が発生。
  • 画面の一部だけ差し替えたいのに、結局ページまるごと再レンダー──というムダが出やすかった。」

📏 4) ルート定義が増えるほどコード分割が粗くなる
👴: 「ファイル名ベースでルートが増えるのは楽だが、

  • 動的ルーティング([id].js など)が多層になるとファイルが散らばり、重複したフェッチやロジックがコピー&ペーストされやすい。
  • ページ単位でしかチャンクが切れないので、同じモジュールを参照する別ページ間でチャンクが重複し、バンドルの“だぶつき”が起こることもあった。
    つまり“増やすほど軽くなる”理想とは逆に、“増やすほどバンドルが複雑”になりがちだったんじゃ。」

🐶: 「ふむふむ…まとめると、

  1. ページ単位が粗くてデータもキャッシュもムダが出た
  2. SSR/CSR の二択で JS が太り、部分最適が難しい
  3. 複雑なレイアウトを組むと状態やスタイルがねじれる
  4. 動的ルートが増えるほどファイルとチャンクが散らかる
    って感じだね!」

👴: 「その通り。Pages Router は“ページを置くだけ”の革命を起こしたが、さらに細やかな制御・性能・構造化を求める声が高まり、Next.js は App Router へと進化したわけじゃ。」

🐶: 「なるほど! 弱点を知ったら、次にどう進化したかも気になってきたワン!」

👴: 「よい好奇心じゃ。App Router ではサーバーコンポーネントや部分ハイドレーションでこの壁を越えておる。続きが聞きたければ、また茶を飲みに来るんじゃぞ。」

App Router 「で、俺が生まれたってわけ」

さきほど説明したPages Routerの課題を解消するために生まれたのがNext.js App Routerになります。

App Routerでは以下のような概念が導入され、Pages Routerの課題を解決しました。

  1. React Server Components 採用で JS バンドル激減
  2. ネストレイアウト & ソフトナビゲーション → 状態を保持したまま部分更新
  3. 組み込み Data CacherevalidateTag() → “静的速度で動的更新”

これらの仕組みが導入されたことで、Next.jsの開発体験は飛躍的に向上しました。
表にすると以下のような感じです。

Pages Router での制約 具体的に何がつらい? App Router が導入した解決策 実際のメリット
レイアウトは _app.tsx 1 枚のみ 画面階層ごとに UI を分けるとコード重複/状態が毎回リセット ネストレイアウト app/blog/layout.tsx など階層ごとに配置 サイドバーやタブの 状態を保持したまま 部分遷移できる
「サーバー or クライアント」二択 SSR は毎回フル HTML 生成+全 JS 配信=初回重い React Server Components
‐ サーバー専用 JS はブラウザへ送らない
‐ Client 部分だけ "use client"
初回バンドル 30〜40 % 減/Selective Hydration で体感速度向上
データ取得は page 外部 (get*Props) だけ バケツリレー Props、同じ API を重複フェッチしがち Server Component 内で await fetch() データと UI を 同じファイルにコロケーション/1 リクエスト内で自動メモ化
キャッシュ粒度=ページ 「ここのカードだけ 60 秒キャッシュ」等が困難 fetch()cache / next.revalidate を直接付与 API 単位で no-store / ISR を宣言でき、静的⇄動的を細かく混在

🐶「まぁ、とりあえずPages Routerの課題を解決したっちゅーことかえ」

具体的に説明していきます。

1. レイアウト1枚だけ問題

Pages Routerは_app.tsxを使ってレウアウトを設定することができました
しかし、設定できるのは1枚だけで、各階層ごとに設定することができなかった


App Routerはネストレウアウトとなっている(例:app/users/layout.tsxapp/dashboard/layout.tsx
各階層にレイアウトを設定することができ、さらにタブの状態を維持したまま部分遷移することができるようになった

Pages Routerでは

🐶『ページAの時はこのレイアウトでページBの時はこのレイアウトで…(あたふたあたふた…)

となっていたのだが、階層ごとにレイアウトを設定できるようになったこと複雑な条件分岐を書かなくて良くなった

🐶「レイアウト1枚だけ問題をどう解決したの?」

🐶: 「おじいちゃん! App Router が“レイアウト1枚だけ問題”を解消したって聞いたけど、そもそも何が困ってたの? わかりやすく教えてワン!」

👴: 「よしイッヌ。じゃあまず“レイアウト”をお弁当箱にたとえてみよう。フタ(ヘッダー)と仕切り(サイドバー)があって、中身(ページの本体)を入れる感じじゃ。」


🗺️ レイアウト1枚だけ問題って?

👴: 「Pages Router では _app.tsxたった一つのお弁当箱だった。だから――

  • どのページも同じ箱を使うので“ユーザー一覧ページ用のフタ”や“ダッシュボード専用の仕切り”を作り分けられない。
  • ページを切り替えるたびに箱ごと作り直すから、タブの開閉状態やスクロール位置がリセット。
  • 共通部品を切り替えたいときは、各ページで if 文分岐を書いたり、状態を Context で上流から吊ったりしてコードがゴチャゴチャ

要するに“お弁当箱が 1 個しかないから、メニューが増えるほど詰め方が窮屈”だったわけじゃ。」

🐶: 「なるほど! 唐揚げ弁当もサンドイッチも同じ箱に詰めるのは大変だワン!」


🧩 App Router がどう変えた?

👴: 「App Router ではフォルダごとに layout.tsx を置ける。つまり入れ子の弁当箱(ネストレイアウト)が作れるんじゃ。」

  • app/users/layout.tsx → “ユーザー管理の箱”
  • app/dashboard/layout.tsx → “管理画面の箱”
  • 上位フォルダの箱はそのまま残し、中身だけ差し替えて部分遷移

🐶: 「ということは――」

  1. ページ間で共通する UI を階層ごとに整理

    • 上の箱: サイト全体のヘッダー
    • 中の箱: ダッシュボード特有のサイドバー
    • 下の箱: タブ切り替えエリア… のようにスッキリ分離。
  2. 状態を持った部品がそのまま生き残る

    • 例: ダッシュボードのサイドバー開閉、タブ選択がページ遷移しても維持
  3. コード分岐が激減

    • 「このページだけヘッダー非表示」みたいな if 文が要らず、箱を分けるだけで済む。

👴: 「加えて、App Router は React Server Components と相性が良く、レイアウト層はサーバー側でレンダリング、動的な中身はクライアントだけを送る――という部分ハイドレーションも実現しやすくなった。だから表示も速いんじゃ。」


🐶: 「まとめると――

  • _app.tsx ひとつ → フォルダごとの layout.tsx で小分け
  • 共通 UI を階層で整理、状態もキープ
  • if 文だらけの条件分岐から解放
  • 部分ハイドレーションで速くて軽い

イッヌでもバッチリわかったワン!✨」

👴: 「よい理解じゃ。App Router は“箱を増やして詰め方を自由にした”おかげで、大規模アプリでも UI とコードの見通しがぐっと良くなったんじゃ。」

2. サーバーorクライアント2択問題

Pages RouterではSSRが使われていました

SSRはサーバー側で完成したHTMLをフロントエンドに送るため、フルハイドレーションなるものが実行されています


そのため、SSRには以下のような課題があった

  • JSバンドルを全部ブラウザに送信していた(ブラウザだと使わないJSもある)
  • フルハイドレーションによるCPUのブロッキング(クリック受付が遅れる)

などです

🐶「ハイドレーションってなに?」

🐶: 「おじいちゃん! ハイドレーションって言葉は聞くけど、まだイメージがボンヤリしてるワン。仕組みをゼロから教えて!」

👴: 「よしイッヌ、散歩しながら順を追って話そうか。」


🎨 まず届くのは“動かないポスター”

👴「ページを開くと、サーバーは最初に HTML だけをブラウザへ送る。これは見た目は完成しているが、ボタンを押しても何も起きない静止画の状態じゃ。」

🐶: 「デパートのショーウィンドウで、まだ動かないオモチャを眺めている感じだワン!」


🚚 次にやって来る“JSバンドル”

👴「続いてブラウザが JavaScript バンドルをダウンロードする。バンドルにはボタンの動きやメニュー開閉など、ページを動かすための部品と説明書が全部入っておる。
バンドルが大きいほど荷物の到着も組み立ても時間がかかる。ネットが遅いと余計に待たされるわけじゃな。」

🐶: 「大きい箱ほど配達も開封も大変だワン!」


💧 ハイドレーション = ポスター全身に命を吹き込む

👴「バンドルが届くとブラウザはページ全体を巡回し、ボタン・リンク・フォーム――あらゆる部品にイベントリスナーを取り付ける。
これがハイドレーション。大事なのは“ページまるごと”対象にする点で、こんなコストが掛かる。

  • DOM 全体をスキャンするので CPU とメモリを消費
  • 配線が多いほど 実行時間が伸びる
  • 大きなバンドルほど ダウンロードが重い
    それでも終われば、クリックや入力がきちんと反応する“生きたページ”になるんじゃ。」

🐶: 「配線工事が終わるまで観客はちょっぴり待つけど、終わった瞬間に全部のオモチャが動き出すんだね!」


⚙️ 例:ブログ記事ページの流れ

👴「実際のブログを想像してみい。

  1. HTML 到着 → 記事本文と画像がパッと描画。しかし“いいね”ボタンは無反応。
  2. JS バンドル到着 → まだ操作不可だが、ダウンロードが進む。
  3. ハイドレーション開始 → いいね・シェア・コメント欄などページ全体に配線。
  4. 完了 → ボタンが光り、コメント投稿もできる状態になる。
    この“ステップ3”がハイドレーションの本体で、ページの規模が大きいほど時間もリソースも多く必要になるんじゃ。」

🐶: 「だから大規模サイトほど“最初は速いのに動き出すまでは長い”って感じるんだね!」


👴: 「その通り。つまりハイドレーションは『静止画をインタラクティブに変える全身工事』じゃと覚えておけばいい。
ポイントは

  • 最初は動かない HTML が届く
  • JS バンドルをダウンロード
  • ブラウザがページ全体へ配線
  • 完了後にやっと動く

仕組みがわかれば、『なぜバンドルを軽くしよう』『ハイドレーションをできるだけ早く終わらせよう』と皆が工夫する理由も見えてくるじゃろう。」

🐶: 「うん! 配線工事と荷物のイメージでバッチリ理解できたワン。ありがとう、おじいちゃん!」

App RouterではReact Server Component(RSC)が採用されています

これはServer ComponentのJSはブラウザには送信しないようになっています

RSCでは"use client";が付与されているファイルはClient Componentと判断され、そのファイルに対してのみハイドレーションが行われます

その結果として、

  1. JSバンドルサイズの減少(任意のファイルのみハイドレーション)
  2. ネットワーク通信の効率化
  3. バイドレーションによるCPUブロッキングの効率化

に繋がりました


さらにServer Componentになったことでawait fetch()を用いたデータフェッチをトップコンポーネント以外で行えるようになります(詳しくは次で説明します)

🐶「RSCになってなにがうれしかった?」

🐶: 「おじいちゃん! Pages Router の SSR(サーバーサイドレンダリング)から App Router の RSC(React Server Components)に変わったら、何がそんなに嬉しいの? 具体的に知りたいワン!」

👴: 「よしイッヌ、ポイントを四つに絞って話そう。途中で道しるべを立てるから注目じゃ。」


⚡ 1. JS バンドルがぐっと小さくなる

👴: 「SSR ではページを描いたあと、ページ全体を動かす JavaScript も必ず送っておった。
RSC では『サーバーだけで完結する部品』には JS を一切付けず、動く所だけを use client と印を付けて送る。
そのぶんダウンロードも実行も軽くなり、初回表示が速くなるんじゃ。」

🐶: 「必要なパーツだけお土産にするから荷物が減るワン!」


🚰 2. “全身配線” が不要になって CPU がお昼寝

👴: 「SSR→ハイドレーションでは、ブラウザがページをくまなく巡回して全要素に配線しておった。
RSC はサーバーで済む所を“ただの HTML”として配り、配線は 動く部品だけ
ブラウザは重たい工事をしなくて済むから、モバイルでも電池持ちがいい。」 (zenn.dev)


🛒 3. データ取得が“欲しい所”でできる

👴: 「SSR 時代は getServerSidePropsページ丸ごと一括フェッチ
RSC ではコンポーネント内で await fetch() が書けるので、小さな部品ごとに直接データを汲める。
バケツリレー props も減り、同じ API を何度も呼ぶときは RSC の自動キャッシュがまとめてくれるんじゃ。」

🐶: 「蛇口が各部屋に付いた感じ! バケツ運びしなくていいワン!」


🔒 4. セキュリティと保守がシンプル

👴: 「サーバーコンポーネントのロジックや環境変数はクライアントへ漏れない
さらに UI の階層に合わせて 'server' と 'client' を混在させられるので、コードの見通しが良くなる。」

🐶: 「秘密のレシピを厨房の外に出さないわけだね!」


👴: 「まとめると――

  1. 小さな JS だけ届けるから速い。
  2. 配線(ハイドレーション)を最小化して軽い。
  3. 部品ごとにデータ取得でき、バケツリレー消滅。
  4. サーバーの秘密は外に出ず、コードも整理しやすい。

Pages Router の SSR が抱えていた“でっかいバンドル・全身配線・データ一括取り”の三重苦を、App Router の RSC がほぼ解消したわけじゃ。」

🐶: 「なるほどワン! 荷物も工事も減って、データもスマートに取れる。だから RSC に切り替わったのは大きな進化なんだね!」

👴: 「その通り。これでイッヌも、動かす所と静的な所を上手に分けながら、速くて軽いサイトを作れるはずじゃ。」

まぁ、とりあえずApp Routerになったことで、RSCをつかうようになり、Pages Routerの苦しかったポイントを色々解消したよってことですね

3. バケツリレー問題

Pages RouterではトップコンポーネントでgetServerSideProps()getStaticProps()などのデータフェッチ関数を用いてデータを取得し、子コンポーネントに渡すという流れになっていた

そのためネストが深くなると、Propsとして渡すデータがどんどん増えていき、管理が大変になっていった…


先ほども説明しましたが、App RouterではSSRではなくReact Server Componentを採用している
そのため任意のコンポーネントをServer ComponentとClient Componentに分割することができるようになりました


これにより、データフェッチもトップコンポーネントで行う必要がなく、Server Compnentであれば、どのコンポーネントでもawait fetch()を使ったデータフェッチが行えるようになりました

🐶「バケツリレー問題はどう解消したの?」

🐶: 「おじいちゃん! Pages Router って“データのバケツリレー”で大変だったよね? App Router に変わってどうラクになったのか知りたいワン!」

👴: 「よしイッヌ。まず“バケツリレー”が何を指すかを思い出そうか。ページ最上位で取ったデータを──」

  1. 親ページ
  2. 子コンポーネント
  3. 孫コンポーネント …

👴: 「――と何段も props で手渡ししていた。これがバケツで水を回すように重労働だったわけじゃ。」

🐶: 「深いツリーほど腕がパンパンになるやつだね!」


🛠️ App Router の処方箋:サーバーコンポーネント

👴: 「App Router では“どの階層でもサーバーで動くコンポーネント”を置けるようになった。具体的に見ると――」

仕組み 効果
layout.tsxpage.tsx だけでなく、任意のコンポーネントを export async function … その場で await fetch() 可能。データを取ったら直下の子にだけ渡せばよいので、バケツリレーが途切れる。
React の自動キャッシュ/リクエスト重複排除 同じ fetch がネスト内で呼ばれても 1 回で済む。
ストリーミング 取れた順に HTML を送り始めるから、親が遅くて子が速いときでも“子だけ先に表示”できる。
サーバー ↔ クライアント分離 インタラクションが必要な部分だけ use client でマーク。データを持ったままクライアントへ小さく渡すので JS バンドルも減量。

👴: 「要は“水道管を階ごとに引いた”ようなものじゃ。欲しい場所で蛇口をひねれば水(データ)が出るから、バケツを担いで階段を上り下りせずに済む。」

🐶: 「おお! 各フロアにウォーターサーバーが置かれたイメージだワン!」


🍱 ついでにうれしい副作用

  • 状態の局所化

    • 取ったデータと表示ロジックが同じファイル内に収まるので読みやすい。
  • キャッシュ粒度の細分化

    • ユーザー一覧だけ 60 秒ごとに再検証、プロフィール欄は 1 日キャッシュ…と部品ごとに設定できる。
  • ページ遷移の高速化

    • 親レイアウトは再利用し、中身の差分だけ取得・描画。たとえデータを再フェッチしても必要最小限。

🐶: 「つまり、バケツリレー問題は――

  • どこでも async サーバーコンポーネント
  • 自動キャッシュで 重複フェッチなし
  • ストリーミングで 見えるのが速い
  • 必要箇所だけ JS を送るから 軽い

って感じでスパッと解消されたんだね!」

👴: 「その通り。App Router は“データを欲しい所で直接汲める水道”を通したおかげで、開発者の腕もコードも軽くなったというわけじゃ。」

🐶: 「スッキリ理解できたワン! これでボクもデータ取り回しでヘトヘトにならずに済むね!」

👴: 「うむ、イッヌよ。次はその水道をどう上手に配管するか、一緒に試してみるかの。」

まとめ

Next.jsはPages Routerに始まり、いろいろな開発課題を解決してきました。

しかし、Pages Routerにももちろん課題はあり、その課題を解決しつつも、従来の課題も解決した最強のフレームワークがNext.js App Routerなんだ!

と僕は未熟ながらも調べていて思いました。


「とりあえず、Next.jsはすごいんだ!」「お、俺も使おう」と思ってくださる人が増えれば幸いでございます。

🐶「Next.jsはとりあえずすごいんだ!!」

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?