logo

Next13の大事そうなところをまとめてみた

2023-01-03
a year ago

開発環境

  • next 13.0.6

前提

2022年12月時点の公式ドキュメント(Next 13 app directory (beta) docs を主に参考にしています。

本題

Special Files

これまでは共通設定を_document.tsx_app.tsxで定義していましたが、ページごとにローディングやエラー、ヘッドなどを配置できるようになりました。

<Layout>
  <Template>
    <ErrorBounday fallback={<Error />}>
      <Suspense fallback={<Loading />}>
        <Page />
      </Suspense>
    </ErrorBounday>
  </Template>
</Layout>
-─ app
    ├── layout.tsx
    ├── template.tsx
    ├── error.tsx
    ├── loading.tsx
    └── page.tsx

【注意点】

  • appディレクトリ直下に配置する場合、ルートファイルとなり共通設定にすることができます。
  • ルートに配置するlayoutは必ずhtmlbodyタグを配置する必要があります。
  • appディレクトリの中ではデフォルトでサーバーコンポーネントになる
  • ファイルを配置すると自動的にPageコンポーネントをラップする
  • サーバーコンポーネントで発生したエラーはクライアント側で表示させる必要があるので、error.tsx’use client’を宣言してクライアントコンポーネントにする

Web fetch() API

fetchAPIを利用してデータフェッチを行う際、キャッシュオプションを設定することでSSG, SSR, ISRを使い分けるようになりました。

何も指定しなければデフォルトでSSGとなります。

# SSG (デフォルト)
fetch(URL, { cache: 'force-cache' })

# SSR
fetch(URL, { cache: 'no-store' })

# ISR
fetch(URL, { next: { revalidate: 10} })

When to use Server vs. Client Components?

サーバーコンポーネントの特徴

  1. サーバーでレンダリングされる(クライアントにjsは送られない)
  2. データフェッチにasync functionを使用できる
  3. Secure keyを使用可能
  4. ブラウザAPIは使用不可
  5. hooks(useState, useEffectなど)は利用不可
  6. Event Listner(onClickなど)は利用不可

クライアントコンポーネントの特徴

  1. ブラウザでjsが実行される
  2. データフェッチはuseEffect, react-query, SWR, useなど利用する
  3. Secure keyを使用不可
  4. hooks(useState, useEffectなど)を使用可能
  5. Event Listner(onClickなど)を使用可能

どう使い分ける?

公式には・・

とあるので、基本的にはクライアントでしかできないこと以外はサーバーでやるのが推奨のようです。

Mutating Data

サーバーコンポーネントでのデータ再取得についてはrouter.refresh()が推奨されています。

こちらはクライアント側(React)の状態を保持しつつ宣言的にデータ取得を行うもので、イベントハンドラーなど何かしらのトリガーでインタラクティブに更新できるようになりました。

Nested Layout

セグメントをネストしていく際、各階層でlayout.tsxを作成すると累積していきます。

Streaming and Suspense

SSRでデータフェッチをする際、プリレンダリングが完了するまではクライアント側で何も表示できません。

なるべく早くコンテンツを表示させなければUXの悪いアプリケーションになってしまいます。

また、データフェッチを行うサーバーコンポーネントのレンダリングができないことが、他の本来はすぐに表示できるコンテンツ(コンポーネント)の表示までも遅らせてしまいます。

そこで、サーバーコンポーネントとSuspenseを組み合わせることで表示に時間のかかるサーバーコンポーネントのみを(例えば)ローディング状態にして、他のコンテンツを表示させることができます。

import { Suspense } from 'react';
import { UsersList, ArticlesList } from '../components';

const SamplePage = () => (
  <>
    <Suspense fallback={<div>Loading..</div>}>
      <UsersList />
    </Suspense>
    <Suspense fallback={<div>Loading..</div>}>
      <ArticlesList />
    </Suspense>
  </>
);

export default SamplePage;
SamplePage.tsx

上記の例ではUsersListが件数が多く、レンダリングコストの高いコンポーネントだと仮定し、ArticlesListはすぐに表示できるコンポーネントと仮定します。

この場合、UsersListのプリレンダリングが完了することを待たずして、ArticlesListはすぐに表示され、インタラクティブに操作可能になります。

さいごに

React18の記事でも述べましたが、さいごにご紹介したStreaming and Suspenseなど並行処理をうまく活用してUXを高めていくことが今後のフロントエンド開発のテーマの1つになるのかなと思うので、サーバーコンポーネントをまずはしっかり理解していきたいです!

参照