Next.js13雑多なメモ

## appディレクトリ

### ざっくり概要

- `app`ディレクトリにあるページはデフォルトで`Server Components`
- ページが`Client Components`である`pages`ディレクトリとは異なる

### RootLayout

- RootLayoutは必須 → `app/layout.tsx`のこと
- Layoutは状態を維持して再レンダリングされない
    - 状態の変更などが関わってくるときはTemplateを使用する
    - Templateを使用する特別な理由がない限り、Layoutを使用することが推奨されている

```tsx
type Props = {
  children: React.ReactNode
}

const RootLayout = ({ children }: Props) => {
  return (
    <html lang="ja">
      <body>
        {children}
      </body>
    </html>
  )
}

export default RootLayout
```

### その他変更点

- `_app.js`と`_document.js`は不要になる → `layout.tsx`に置き換わる
- `next/head`は`head.tsx`に置き換わる（予定）
- APIルートは従来通り`pages/api/*`ディレクトリで定義する

## ServerComponents

- appディレクトリ内のコンポーネントは、特殊ファイルやコロケーションされたコンポーネントも含め、デフォルトですべて`React Server Components`
    - `Server Components`と`Client Components`により、Reactはクライアントとサーバーでレンダリングできるようになり、コンポーネントレベルでレンダリング環境を選択することができるようになった
- 追加のJavaScriptは、`Client Components`の使用により、アプリケーションにクライアントサイドのインタラクティブ性が必要な場合にのみ追加される
- `Client Component`を使用する必要があるまでは、`Server Component`を使用することを推奨

## Client Components

- `Client Components`を使用するときは`'use client';` 宣言をする
- `Client Components`は、クライアント上でレンダリングされる
- Next.jsでは、`Client Components`をサーバー上でプリレンダリングして、クライアント上でハイドレーションすることもできる
- `Server Component`と`Client Component`は、同じコンポーネントツリーに挟み込むことができる
- `Server Component`がサーバー専用のコード（データベースやファイルシステムのユーティリティなど）を持つ可能性があるため、`Client Components`の中に`Server Components`をインポートすることには制限がある

## データフェッチ

### ざっくり概要

- `getServerSideProps`、`getStaticProps`、`getInitialProps`は、`app`ディレクトリではサポートされない。よりシンプルなAPIに置き換わった。→ fetchのオプションで指定する
- SSG、SSRなどページ単位でのレンダリングという概念ではなく、コンポーネントレベルでデータのフェッチ（静的・動的）を使い分ける新しいメンタルモデル
- `Server Components`はJavaScriptバンドルを送信しないため、クライアントへのJavaScriptの送信が少なくなる。`Client Components`でもデータフェッチは可能だが、特別な理由がない限り、データを直接必要とする`Server Components`内部でのデータフェッチを推奨。
- `Client Components`でのデータ取得はSWRやReact Queryなどのサードパーティライブラリを使用することを推奨。将来的には、Reactの`use()`フックを使用して、`Client Components`からデータを取得することも可能になる。

### サーバーコンポーネント間でのフェッチリクエストの共有

- `Server Components` では`props`は使用せず、データが必要な箇所でフェッチリクエストを送ることが推奨されている。
- フェッチリクエストはサーバーコンポーネントで自動的に重複排除されるので、各ルートセグメントは重複したリクエストを気にしなくて良い。キャッシュから同じ値を読み取る。

### fetch()

- Next.js は`fetch()`関数の`options`オブジェクトを拡張し、サーバー上の各リクエストで独自の持続的キャッシュ動作を設定できるようになった。
- コンポーネントレベルのデータ取得とあわせて、データが使用される場所で、アプリケーションコード内で直接キャッシュを設定することが可能になる。
- Reactはfetchを拡張してリクエストの自動的な重複排除を提供し、Next.jsはfetch optionsオブジェクトを拡張して各リクエストに独自のキャッシュと再バリデーションのルールを設定できるようになる。

### 静的データフェッチ（デフォルト）

- デフォルトでは、fetch()リクエストの結果をキャッシュする。
- `getStaticProps`に似ている
- `force-cache`がデフォルトで省略可能

```tsx
// `app` directory

async function fetchData() {
  const res = await fetch('https://.../data'); // cache: 'force-cache' is the default
  const data = await res.json();
  return data;
}
```

### ダイナミックレンダリング

- すべてのリクエストでリフェッチされる
- `getServerSideProps`に似ている

```tsx
// `app` directory

async function fetchData() {
  const res = await fetch(`https://.../data`, { cache: 'no-store' });
  const data = await res.json();
  return data;
}
```

### データの再検証

- 有効期限でキャッシュされる
- `getStaticProps`に`revalidate`オプションをつけたものに似ている。

```tsx
// `app` directory

async function fetchData() {
  const res = await fetch(`https://.../data`, { next: { revalidate: 10 } });
  const data = await res.json();
  return data;
}
```

## サードパーティ

- クライアントのみの機能に依存するサードパーティコンポーネントを、独自のクライアントコンポーネントでラップすることができる
- ほとんどのサードパーティコンポーネントは、`Client Components`の中で使用される可能性が高いので、ラップする必要はないかもしれないが、プロバイダコンポーネントは例外で、Reactの状態とコンテキストに依存しており、通常はアプリケーションのルートで必要になる

```jsx
'use client';

import { AcmeCarousel } from 'acme-carousel';

export default AcmeCarousel;
```

## 参考資料

https://beta.nextjs.org/docs/getting-started

https://zenn.dev/jtakahashi64/articles/a9d2ae3285ceb6

https://dev.classmethod.jp/articles/next-js-13-sample/