Next.js 13の Route segmentsの仕組み・ServerComponentでできることできないこと

## Next.js 13での主な新機能

Next.jsはバージョンアップされるたびに新しい機能が次々に追加されています。
今回はNext.js 13の中からRoute segmentsとServer Componentsの新機能に絞って学んだことのアウトプットの記事です。

https://nextjs.org/blog/next-13

**Next.js 13での主な新機能**
**1.Route segments** ←今回の記事のアウトプット
**2.Server Components** ←今回の記事のアウトプット
3.Streaming
4.Layouts

参考・引用しているのはこちらのUdemyの動画です。Next.js13の機能をハンズオンで学べて分かりやすく、おすすめです！

https://www.udemy.com/course/nextjs-supabase-app-directory/


## Route segments


appディレクトリの中にはフォルダを階層状に作っていくことができ、そのフォルダ１つ１つがセグメントに対応しています。各セグメントはURLパスでアクセスすることができます。
![terminology-component-tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288047/fd62f949-83e7-b4e4-9434-a000dab34dad.png)
[公式ドキュメント](https://nextjs.org/docs/app/building-your-application/routing) より引用

アプリケーション全体が１つのツリー構造になっていて、そこから分岐しているそれぞれのかたまりのことを**サブツリー**と呼んでいます。
各セグメントを表すフォルダの中にはファイルを作成することができ、appディレクトリの中ではあらかじめ決められた特殊なファイル名というものが存在します。

それがpage.tsx、layout.tsx、error.tsx、loading.tsx、あとはテンプレートとHeadというものがあります。
```
<Layout>
 <ErrorBoundary fallback={<Error />}>
  <Suspense fallback={<Loading />}>
   <Page />
  </Suspense>
 </ErrorBoundary>
</Layout>
```
**page.tsx**は対象のセグメントのユーザーインターフェースを記述するファイルコンポーネントになっています。
**layout.tsx**はページのコンポーネントに対するレイアウトに対応しています。

**loading.tsx**を追加するとページのコンポーネントをラップする形で１つサスペンスが自動的に付与され、fallbackのスケルトンの内容をloading.tsxのファイルな中でカスタマイズしていくことができます。

さらに、**error.tsx**のセグメントのフォルダの中に追加していくと、Next.jsによってサスペンスをラップする形でエラーバウンダリが自動的に追加され、fallbackで表示させるエラーの内容をカスタマイズしていくことができます。

appディレクトリの中は、すべてのコンポーネントがデフォルトで**サーバーコンポーネント**と認識されています。

### head.tsxの廃止
Next.js 13.4 以降では、App Routerがstable版となり、beta版で存在していた head.tsxが廃止になりました。

titleの値などは、`export const metadata`を使用しlayout.tsxに設定します。

```layout.tsx
import NavBar from './components/nav-bar'
import './globals.css'
 
export const metadata = {
  title: 'Nextjs App',
  description: 'Generated by create next app',
}
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <NavBar />
        {children}
      </body>
    </html>
  )
}
```

https://nextjs.org/docs/app/api-reference/functions/generate-metadata

## Server Components
Next.js 13では、目玉機能としてServer Componentsが導入されました。

>Server Components
The app/ directory introduces support for React's new Server Components architecture. Server and Client Components use the server and the client each for what they're best at - allowing you to build fast, highly-interactive apps with a single programming model that provides a great developer experience.
With Server Components, we're laying the foundations to build complex interfaces while reducing the amount of JavaScript sent to the client, enabling faster initial page loads.
When a route is loaded, the Next.js and React runtime will be loaded, which is cacheable and predictable in size. This runtime does not increase in size as your application grows. Further, the runtime is asynchronously loaded, enabling your HTML from the server to be progressively enhanced on the client.



:::note info
翻訳
app/ディレクトリは、Reactの新しいServer Componentsアーキテクチャのサポートを導入しています。Server ComponentsとClient Componentsは、サーバーとクライアントをそれぞれ得意とする用途に使用します - 素晴らしい開発者体験を提供する単一のプログラミングモデルで、高速で高度にインタラクティブなアプリを構築できます。

Server Componentsでは、クライアントに送信されるJavaScriptの量を減らしながら、複雑なインターフェイスを構築するための基礎を築き、より高速な初期ページロードを可能にします。

ルートがロードされると、Next.jsとReactのランタイムがロードされます。このランタイムは、アプリケーションが大きくなってもサイズが大きくなることはありません。さらに、ランタイムは非同期にロードされるため、サーバーからのHTMLをクライアントで徐々に拡張することができます。
:::


### Server ComponentsとClient Componentの違い


|| Server Components | Client Component |
|:-----------|:-----------|:-----------|
|①| **サーバーでRendering**される (= Javascriptはクライアントに送られない)     | **ブラウザ**でJavascriptが実行される        | 
|②|Data fetchに**async/await**を使用できる   | Data fetchに**async/await**が使用できない(=**useState,useEffect,SWR,React-query**を使用する必要がある)      | 
|③| **Secure key**を使用可能      | **Secure key**を使用不可       |
|④| **Brower API**は使用不可      |      **Brower API**は使用可能     |
|⑤| **useState,useEffect等**は使用不可       | **useState,useEffect**を使用可能       |
|⑥| **Event listener(onClick等)** は使用不可    | **Event listener(onClick等)** を使用可能     | 


**サーバーコンポーネントの特徴**
①サーバーコンポーネントはサーバーサイドでJavascriptが実行されてレンダリングされるため、サーバーコンポーネントに含まれているJavascriptやnpmパッケージはクライアントに送られないメリットがあります。
②コンポーネントレベルでasync/awaitを使用できるため、Data fetchを簡単に記述することができます。
③サーバーコンポーネントの方ではシークレットな環境変数を読み込むこと(envファイル等)ができます。
④一方で、サーバーで実行されるため、ブラウザ特有のAPIなどは実行することができません。
⑤⑥ React特有のuseState,useContext,useEffectやonClick,onSubmitで使われるイベントリスナーはサーバーコンポーネントで使用することはできません。

**クライアントコンポーネントの特徴**
①ブラウザでJavascriptが実行されます。
②,③データフェッチをする場合は、サーバーコンポーネントのようにコンポーネントの階層でasync functionを使用することができないので、useEffect,ReactQuery,SWR,use(新しいhooks)を使用する必要があります。
④完全なシークレットキーをブラウザで使用することはできません。
⑤⑥ useState,イベントリスナーは全て使用することができます。

ファイルをクライアントコンポーネントに設定したい場合は、１行目に`'use client'`と記述します。
![スクリーンショット 2023-07-23 17.50.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288047/7e4f25cc-f40d-60fc-f089-478458599fce.png)

### インポートのルール
サーバーコンポーネントからクライアントコンポーネントをインポートすることはできますが、クライアントコンポーネントの方からサーバーコンポーネントをインポートして使用することはできません。

```app/page.tsx
// NG
'use client'
import ServerComponent from './ServerComponent'

~省略~

return(
    <>
     <ServerComponent />
    </>
)
```

例外は、クライアントコンポーネントの**チルドレン**としてサーバーコンポーネントを渡すことはできます。

```app/page.tsx
// OK 
'use client'
import ClientComponent from './ClientComponent'
import ServerComponent from './ServerComponent'

~省略~

return(
    <ClientComponent>
     <ServerComponent />
    </ClientComponent>
)
```
上記の例外では、Reactがサーバーコンポーネントを事前にサーバーサイドをレンダリングしておかなければならないということを認識します。
クライアントサイドでクライアントコンポーネントが実行されるときにチルドレンのところにすでに実行されているサーバーコンポーネントのレンダリング結果がpropsで渡されることによって、クライアントコンポーネントで実行することができます。



## 参考
https://nextjs.org/blog/next-13

https://www.udemy.com/course/nextjs-supabase-app-directory/

https://reffect.co.jp/react/next-js-13/

https://zenn.dev/sumiren/articles/f39a151e7320d5

https://zenn.dev/andraindrops/articles/a9d2ae3285ceb6?redirected=1