初学者なりにApp Routerを説明したい

## 目次
1. はじめに
2. そもそもNext.jsとは
3. App Routerについて
   3-1. まず従来のPages Routerとは
   3-2. App Routerの特徴やメリット
      - ルーティングの方法
      -  レイアウトをネストできる
      -  デフォルトでReact Server Componentとなる
      -  データ取得処理がシンプルになった
4. 終わりに


## 1. はじめに

### 本記事のゴール
Next.jsの勉強を始めましたが、基本的な理解がまだ足りていないと感じるので、まずはApp Routerの特徴について、ある程度説明できるようになることをゴールにしています。

### 筆者のスキルレベル
- React含めて実務経験は0
- Next.jsのチュートリアルは一通り行った程度です（1から書くのはまだ難しい）
（本記事を書くにあたり、[こちら](https://zenn.dev/hathle/books/next-supabase-chat-book/viewer/00_first)の記事に沿ってチャットアプリを作成したり、
[こちら](https://www.udemy.com/course/nextjs13_learning_with_microblog/?couponCode=ST15MT100124)のUdemyを一通り実施した）

## 2. そもそもNext.jsとは
- Reactをベースにした**フレームワーク**
- その上で、ルーティングやSSR（サーバーサイドレンダリング）などReactではカバーできない範囲も含めアプリケーション開発に必要な機能を備えています
- State of JavaScript 2023では一番使用率が高く、その人気が分かります

![stateofjs2023-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3876203/66b8c7fb-8dc1-eb4e-f2da-ebe83ffe6bb6.png)
（画像引用: [https://www.publickey1.jp/blog/24/state_of_javascript_20231reactnextjs23500.html](https://www.publickey1.jp/blog/24/state_of_javascript_20231reactnextjs23500.html)）

### 2-1. ちなみにフレームワークとは
- アプリ開発でよく利用される機能があらかじめ揃えられたもの。**実装に必要な骨組み**がすでにできているイメージです。
- 基本的な機能が揃っているので、実装の負担を減らすことができます

:::note info
**ライブラリとの違い**
ライブラリはあくまで機能、つまり部品のみが集まっているイメージです。
ReactやjQueryなどがライブラリにあたります。

対してフレームワークは骨組みも備えているイメージです。
フレームワークはすでに必要な機能が揃っている分、実装面の自由度は低くなるのがデメリットだが、ライブラリはその逆で、**必要な機能だけ持ってこれる**ので実装の自由度は高くなります。
:::

### 2-2. Reactと比べた際のNext.jsのメリット（一例）
#### **クライアント環境に依存しないレンダリング**
Reactはクライアント側でレンダリングを行うが、ページ数が多いサイトを閲覧する際や、ユーザー環境によっては**初回読み込み速度が遅くなる**可能性があります。

対してNext.jsが基本**サーバー側でレンダリングする**ので、上記理由によってユーザビリティを損ないません。

#### **ルーティング設計を直感的に行える**
React単体にはルーティング機能（= 特定のURLが指定された時に、どのファイルを実行するか決定する）はなく、React-Routerのような別のライブラリが必要になります。
Next.jsでは`app`（13.xより前は`pages`）ディレクトリにファイルを配置すると、URLとファイルを自動的に紐付けてくれます。
※App Router とPages Routerに関しては後述

上記以外にもSEOの改善など、Reactでは対応できない機能を備えています。

## 3.App Routerについて
### 3-1. まず従来のPages Routerとは
デフォルトで`src/pages`ディレクトリが用意されており、配下に作成したファイル名がそのままURLとして適用されるので分かりやすい。
下記blogのように、`pages`配下でネストしても、同じくそのフォルダ名がURLに適用される。
```
pages
┗ index.tsx  // → / でアクセス可能
┗ blog
  ┗ articles.tsx // → blog/articles でアクセス可能
```


### 3-2. App Routerの特徴やメリット
Next.js13からリリースされた機能。
13.4から安定版となりました。

:::note info
ちなみに`create-next-app`でプロジェクトを作成した場合、App Routerを使用するか聞かれるので、Yesと答えると適用される。（Noにすると従来のPages Routerの構成になる）
:::

<br>
Pages Routerとの主な違いは下記。

#### 3-2-1. ルーティングの方法
- `pages`ではなく、`app`ディレクトリに名称変更された
- Pages Routerでは`pages`配下に作成したファイルがそのままルーティングされていたが、`page.tsx(js / jsxファイルでもOK)`というファイル名にした場合のみルーティング対象となり、ブラウザ上で確認することができる

```
app
┗ index.tsx  // → pageの名称ではないので404になる
┗ page.tsx  // → / でアクセス可能
┗ blog
  ┗ articles.tsx // → pageの名称ではないので404になる
  ┗ page.tsx // → blog/ でアクセス可能
```

#### 3-2-1-1. ルーティングの方法が変わったことによるメリット

##### ルーティングしたいファイルか否かで分けることができる
前述の通り、Pages Routerでは全てのファイルがルーティングの対象になっていました。
ただ実装していると、ルーティングの対象にする必要がないファイルもでてきます。

例えば今回作成したチャットアプリでは、チャット内容を表示する吹き出しを下記のように`post-item.tsx`componentとして実装していました。
```
app
┗ components
  ┗ post
    ┗ post-item.tsx // components/post/post-itemにアクセスしても404となる
```
Pages Routerの場合、このファイルにもURLでアクセスできてしまいますが、App Routerだと不必要にルーティングに影響しません。

つまりルーティングしたい場合と、それ以外（レイアウトにのみ使用したい場合など）で**役割でファイルを明確に分ける**ことができます

#### 3-2-2. レイアウトをネストできる
ヘッダーなど、ページ共通で表示したいパーツは`layout.tsx`に記載することで表示することができます。
更に新規でディレクトリ追加（下記では`test`） & `test/layout.tsx`を追加した時、`test/page.tsx`ではルートの`layout.tsx`を継承した状態で`test/layout.tsx`が表示されます。

```
app
┗ layout.tsx
┗ test
  ┗ layout.tsx // ルートのlayout.tsxの中に、更に`test/layout.tsx`が表示される
  ┗ page.tsx
```

#### 3-2-3. デフォルトでServer Componentとなる
従来のPages Routerでは作成したcomponentがデフォルトでCSRとなる。簡単にいうとコンポーネントに記載したjsがクライアントで実行されていました、
App Routerではデフォルトで[Server Component](https://ja.next-community-docs.dev/docs/app-router/building-your-application/rendering/server-components)（以下SC）となります。

SCによって、以下のようなメリットが生まれました。

- 各componentの役割（サーバー or クライアントのどちらで実行したいか）が明確になるので**保守性が向上**する
- 従来jsはクライアント側で実行されていたが、サーバーで実行できることにより**無駄にクライアント側へjsが送信されるのを防ぐ**　etc


もしApp RouterでClient Componentにしたい場合は、ファイル1行目に下記のように`'use client'`と記載します。
```
'use client'

const Hoge = () => {
    return (
        <div>
        </div>
    )
}
```

:::note info
ちなみに・・・
Server ComponentではReactの**useEffect**や**useState**などは使えません。(これらはクライアントサイドで動くため)

console.logもブラウザの検証ツールでは表示されません。
代わりにVscode上などのターミナルで確認でき、処理がサーバーで動いていることが分かります。

▼SCに`console.log('on')`と記載してみました。
![スクリーンショット 2024-09-04 17.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3876203/6c35d008-39d4-2952-05e5-e01b921de386.png)
:::

#### SCの使い分け
現状の自分の理解では、下記のようなパターンではclient componentにし、
それ以外では基本SCのままで実装するイメージです。

- 質問内容の送信処理など、**イベントハンドラを付与したい**時
- **useEffect**や**useState**を使用したい時


#### 3-2-4. データ取得処理がシンプルになった

まず前提として、2-2-3で触れたCSR以外に、next.jsには下記3種類のレンダリング方法があります。

- Static Site Generator（SSG）
- Server Side Rendering (SSR)
- Incremental Static Regeneration (ISR)

▼各レンダリングの特徴は公式を参考にいただけると幸いですmm

https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation

https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering

https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration

#### 3-2-4-1. getStaticPropsやgetServerSidePropsが不要になった
Pages Routerでは`getStaticProps`や`getServerSideProps`を使用して上記レンダリング方法を指定する必要がありました。

対してApp Routerでは`getStaticProps`や`getServerSideProps`は無くなり、下記のようにfetchに引数を与えることでシンプルに指定することができます。

```
// SSG
// ※SSGは初期値なのでわざわざ下記を記述する必要はありません。
 const res = await fetch(URL, { cache: ‘force-cache' });

// SSR
 const res = await fetch(URL, { cache: 'no-store'});

// ISR 
 const res = await fetch(URL, { next: { revalidate: 10 } }));
```

#### 3-2-4-2.  SSGやSSRが同一ページのコンポーネントで併用できるようになった
Pages Routerではデータの取得タイミングがページ単位で決められていました。

例えばgetStaticPropsを使用したページはビルド時にデータを取得することになり、
getServerSidePropsを当該ページのコンポーネントで併用することはできません。

対してApp Routerでは同一ページ内でもSSGやSSRを**併用することができます**。

## まとめ
初学者的に感じたApp Routerの特徴やメリットをざっくりとですがまとめてみました。

個人的にはgetStaticPropsやgetServerSidePropsが無くなり、fetchで制御できるようになったことなど、App Routerの方がよりシンプルかつ分かりやすくなった印象です。

今後の制作でも、これらの特徴を理解した上で効果的にApp Routerを導入していきたいと思います。

## 参考

https://www.pentasecurity.co.jp/pentapro/entry/framework_library

https://kinsta.com/jp/blog/nextjs-vs-react/

https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/

https://zenn.dev/collabostyle/articles/7377d383430bf3

https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts

https://www.northdetail.co.jp/blog/3480/

https://postd.cc/how-react-server-components-work/#01

https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#nextjs-%E3%81%AE%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E7%A8%AE%E5%88%A5%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6pages-router

https://zenn.dev/tasugi/articles/d05c445bc79f09