appディレクトリ
ざっくり概要
-
app
ディレクトリにあるページはデフォルトでServer Components
- ページが
Client Components
であるpages
ディレクトリとは異なる
RootLayout
- RootLayoutは必須 →
app/layout.tsx
のこと - Layoutは状態を維持して再レンダリングされない
- 状態の変更などが関わってくるときはTemplateを使用する
- Templateを使用する特別な理由がない限り、Layoutを使用することが推奨されている
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
がデフォルトで省略可能
// `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
に似ている
// `app` directory
async function fetchData() {
const res = await fetch(`https://.../data`, { cache: 'no-store' });
const data = await res.json();
return data;
}
データの再検証
- 有効期限でキャッシュされる
-
getStaticProps
にrevalidate
オプションをつけたものに似ている。
// `app` directory
async function fetchData() {
const res = await fetch(`https://.../data`, { next: { revalidate: 10 } });
const data = await res.json();
return data;
}
サードパーティ
- クライアントのみの機能に依存するサードパーティコンポーネントを、独自のクライアントコンポーネントでラップすることができる
- ほとんどのサードパーティコンポーネントは、
Client Components
の中で使用される可能性が高いので、ラップする必要はないかもしれないが、プロバイダコンポーネントは例外で、Reactの状態とコンテキストに依存しており、通常はアプリケーションのルートで必要になる
'use client';
import { AcmeCarousel } from 'acme-carousel';
export default AcmeCarousel;
参考資料