今年初めにNext.js触れることになった時、調べてたやつ。
会社のプロダクトはPages Routerで作成しているものと、App Routerで作成しているものがあるので違いを知っておきたく。

App Routerとは

  • Next.jsのバージョン13.4で安定版として登場したルーティングシステム
  • React Server Components(RSC)を基盤としており、サーバーサイドでの処理を可能にすることで、従来のPages Routerよりもパフォーマンスの向上を図っている
  • ディレクトリ構造ベースのルーティングシステム

Pages Routerからアップデートの想い

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

フレームワークの利用が増えるにつれて、開発者がフレームワークを使って構築したいインターフェースの種類も増えてきた。

レイアウトの定義、UIの入れ子、ローディングとエラー状態の定義等、既存のルーターに後付けするのは難しかった。

フレームワークのあらゆる部分がルーターを中心に設計されなければならない。 ページ遷移、データのフェッチ、キャッシュ、データの変異と再検証、ストリーミング、コンテンツのスタイリングなどなど。

ルーターをストリーミングに対応させレイアウトのサポートを強化したいという要望を解決するため。

Pages Router とApp Routerの違い

App RouterPages Router
ルーティング方式/app配下にファイル・ディレクトリを置く
1ディレクトリ=1ページ

ルート:/app/page.js
/pages配下にルーティングの対象となるファイルやディレクトリを置く
1ファイル=1ページ

ルート:/pages/index.js
初期コンポーネントサーバーコンポーネントとして設定
サーバー側でレンダリングし、クライアントに送信
※getStaticProps,getServerSidePropsは不要となる

※ファイルの一行目に「use client」と記述することでクライアントコンポーネントとして機能させることもできる
クライアントコンポーネントとして設定
クライアント側でレンダリング
fetchしたデータ対応の変更データフェッチの際に自動でキャッシュする機能が備わっている
→2回目以降のフェッチはキャッシュが利用できるためパフォーマンスの低下が起こりづらい

※自動キャッシュ機能が備わったことで親子間でのpropsによるデータの受け渡しが不要となった

・4つのキャッシュ
同一のフェッチを繰り返す
→パフォーマンスの低下
メタデータの設定方法app/page.js

export const metadata: Metadata = {
title: "Next.js Blog",
description: "Generated by create next app",
};


もしくは
export async function generateMetadata() {
   return {
     title: "TEST",
   }
}
/pages/index.js

<Head>
<title>My page title</title>
</Head>
リダイレクトimport { useRouter } from "next/navigation"import { useRouter } from "next/router"
共通コンポーネント/app/layout.tsxのroot layoutが必ず必要。_app.js・・・全ページに必要な処理
_document.js・・・htmlタグやboduタグの定義を行う
その他・特別な意味を持つファイルが追加
・特別な意味を持つディレクトリが追加

layout.js,template.jsが登場

サーバーコンポーネントで処理する利点

App routerはデフォルトでサーバーコンポーネントとなっており、こちらを積極的に使用するべき

なぜか?

  1. データフェッチが高速になる
    クライアントからデータを取得するよりもサーバー側から取得する方が処理が早い。(APIやデータセンターと物理的に近い位置にあるから)
  2. サーバー側でレンダリングされる(SSR)されるのでJSバンドルサイズが削減される
    クライアントサイドでのJSの実行やDOM操作が発生しないから初期表示やパフォーマンスの改善をすることができる (JSバンドルサイズ(クライアント側で処理するJS総量)が大きいと初期ロードに時間がかかるため、なるべく、サーバー側で処理をしてクライアント側での負荷を減らしたい。クライアントコンポーネントはJSバンドルに含まれてくる) →サーバーコンポーネントはRSC Payloadとして転送されるため、転送量が多くなる
  3. クライアントのスペックにほぼ依存しなくなる
    サーバー側で処理した結果をクライアントで表示するので、PCやSPの端末のスペックに依存しにくくなる
  4. SEOの向上
    ・完全なHTMLの状態でクライアントに表示される(サーバー側で構築し完全な状態でクライアントに渡される→クローラに完全な状態で見せることができる)
    ・ページ表示速度が向上する
    ・動的メタデータ設定が可能
  5. セキュリティの強化
    サーバー側で実行される=クライアント側で漏洩しにくくなる

サーバーコンポーネントでやるべきこと

  • APIやDBからのデータ取得 → サーバーから直接呼ぶので、
    • 秘密鍵(APIキーなど)を安全に保持できる
    • サーバー → サーバー通信なので高速
    • ブラウザに余計なJSを送らなくて済む(軽い)
  • 例:
    • 初期表示の天気データ取得
    • DBからユーザー情報を引っ張って SSR

クライアントコンポーネントでやるべきこと

  • ユーザーの操作に応じた処理 → ブラウザで実行されるので、
    • onClick, onChange などのイベントを処理できる
    • useState, useEffect が使える
  • 例:
    • 「検索ボタンをクリックして天気を更新」
    • 「フォームに入力した都市を状態管理」
    • 「グラフの表示を切り替える」

Pages RouterとApp Routerのディレクトリ構成

Pages Router

Pages Routerでは/pagesディレクトリは以下のファイル構造がURLの構造になる

  • 1ファイル=1ページ
  • ファイル名がURLになる
  • pasesフォルダ内使用
pages/
├── _app.tsx                   # グローバルレイアウト (Client Component)
├── index.tsx                  # ルート: / (Client Component)
├── about.tsx                  # ルート: /about (Client Component)
├── products/
│   ├── index.tsx              # ルート: /products (Client Component)
│   └── [id].tsx               # ルート: /products/[id] (Client Component)
└── api/
    └── products.tsx           # API route: /api/products

components/
├── Header.tsx                 # 共通ヘッダー (Client Component)
├── Footer.tsx                 # 共通フッター (Client Component)
├── ProductList.tsx            # 製品リスト (Client Component)
└── ProductFilter.tsx          # 製品フィルター (Client Component)

App Router

ディレクトリ切ってその中にpages.tsxを作成する

app
    └──  (Auth)                # ルートグループ。URLには影響しないが、関連するページをグループ化する
        ├── layout.tsx         # 共通化したいレイアウトを定義する
        └──  signin
             └── page.tsx      # /signinにアクセスした際に表示する内容を定義する

appフォルダ内のファイルの意味

app/
├── page.js           --> 一番最初に読み込まれるファイル
├── route.js          --> APIの定義(page.jsと共存不可)
├── layout.js         --> 共通の見た目
├── loading.js        --> 読み込み中の画面
├── error.js          --> エラー時の画面
├── global-error.js   --> グローバルエラー画面
├── templete.js       --> 共通の見た目
├── default.js        --> デフォルトの画面
└── not-found.js      --> notFound関数がスローされたときの画面

参考:

https://zenn.dev/blueish/articles/4b2ae3781ade57
https://rakuraku-engineer.com/posts/nextjs-app/

c.sakyou

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA