diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea7..b5c68e5 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,7 +4,6 @@ about: Create a report to help us improve title: '' labels: '' assignees: '' - --- **Describe the bug** @@ -12,6 +11,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] **Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/issue_template.md b/.github/ISSUE_TEMPLATE/issue_template.md index 4be775c..e04efde 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.md +++ b/.github/ISSUE_TEMPLATE/issue_template.md @@ -4,7 +4,6 @@ about: Standard issue template for Nextjs-docs-ja title: '' labels: '' assignees: '' - --- #### Description diff --git a/docs/01-app/01-getting-started/02-layouts-and-pages.mdx b/docs/01-app/01-getting-started/02-layouts-and-pages.mdx new file mode 100644 index 0000000..33b6566 --- /dev/null +++ b/docs/01-app/01-getting-started/02-layouts-and-pages.mdx @@ -0,0 +1,308 @@ +--- +title: 'レイアウトとページを作成する方法' +nav_title: 'レイアウトとページ' +description: 'Next.jsアプリケーションでレイアウトとページを作成し、リンクする方法を学びます' +related: + title: 'このページで言及されている機能についてもっと学びましょう' + links: + - app/api-reference/file-conventions/layout + - app/api-reference/file-conventions/page + - app/api-reference/components/link +--- + +Next.jsは**ファイルシステムに基づくルーティング**を使用しています。これにより、フォルダやファイルを使ってルートを定義できます。このページでは、レイアウトやページの作成方法、およびそれらをリンクする方法を案内します。 + +## ページを作成する {#creating-a-page} + +**ページ**とは、特定のルート上でレンダリングされるUIのことです。ページを作成するには、`app`ディレクトリ内に[`page`ファイル](/docs/app/api-reference/file-conventions/page)を追加し、Reactコンポーネントをデフォルトエクスポートします。たとえば、インデックスページ(`/`)を作成するには: + +page.js 特殊ファイル + + + + +```tsx title="app/page.tsx" switcher +export default function Page() { + return

Hello Next.js!

+} +``` + +
+ + +```jsx title="app/page.js" switcher +export default function Page() { + return

Hello Next.js!

+} +``` + +
+
+ +## レイアウトを作成する {#creating-a-layout} + +レイアウトとは、複数のページ間で**共有される**UIです。ナビゲーション時にレイアウトは状態を保持し、対話可能であり、再レンダリングされません。 + +[`layout`ファイル](/docs/app/api-reference/file-conventions/layout)からReactコンポーネントをデフォルトエクスポートすることで、レイアウトを定義できます。このコンポーネントは、[レイアウト](#nesting-layouts)またはページとなる`children`プロップを受け入れる必要があります。 + +たとえば、インデックスページを子として受け取るレイアウトを作成するには、`app`ディレクトリ内に`layout`ファイルを追加します: + +layout.js 特殊ファイル + + + + +```tsx title="app/layout.tsx" switcher +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {/* レイアウトUI */} + {/* ページやネストされたレイアウトをレンダリングしたい場所にchildrenを配置 */} +
{children}
+ + + ) +} +``` + +
+ + +```jsx title="app/layout.js" switcher +export default function DashboardLayout({ children }) { + return ( + + + {/* レイアウトUI */} + {/* ページやネストされたレイアウトをレンダリングしたい場所にchildrenを配置 */} +
{children}
+ + + ) +} +``` + +
+
+ +上記のレイアウトは、`app`ディレクトリのrootに定義されているため、[root レイアウト](/docs/app/api-reference/file-conventions/layout#root-layouts)と呼ばれます。 + +### Root レイアウト(必須) {#root-layout-required} + +root レイアウトは最上位レベルで定義され、すべてのルートをラップします。このレイアウトは**必要**であり、`html`および`body`タグを含める必要があります。 + +## ネストされたルートを作成する {#creating-a-nested-route} + +ネストされたルートは、複数のURLセグメントで構成されるルートです。たとえば、`/blog/[slug]`ルートは3つのセグメントで構成されています: + +- `/` (Root セグメント) +- `blog` (セグメント) +- `[slug]` (Leaf セグメント) + +Next.jsでは: + +- **フォルダ**がURLセグメントにマッピングされるルートセグメントを定義するために使用されます。 +- **ファイル**(`page`や`layout`など)は、セグメントに表示されるUIを作成するために使用されます。 + +ネストされたルートを作成するため、フォルダをネストすることができます。たとえば、`/blog`のルートを追加するには、`app`ディレクトリに`blog`というフォルダを作成します。その後、`/blog`を公開アクセス可能にするために`page`ファイルを追加します: + +blogフォルダとpage.jsファイルを示すファイル階層 + + + + +```tsx title="app/blog/page.tsx" switcher +import { getPosts } from '@/lib/posts' +import { Post } from '@/ui/post' + +export default async function Page() { + const posts = await getPosts() + + return ( + + ) +} +``` + + + + + + +```jsx title="app/blog/[slug]/page.js" switcher +import { getPosts } from '@/lib/posts' +import { Post } from '@/ui/post' + +export default async function Page() { + const posts = await getPosts() + + return ( + + ) +} +``` + + + + +フォルダをネストし続けて、ネストされたルートを作成できます。たとえば、特定のブログ記事のルートを作成するには、`blog`内に新たに`[slug]`フォルダを作成し、`page`ファイルを追加します: + +blogフォルダ内にネストされたslugフォルダとpage.jsファイルを示すファイル階層 + + + + +```tsx title="app/blog/[slug]/page.tsx" switcher +function generateStaticParams() {} + +export default function Page() { + return

Hello, Blog Post Page!

+} +``` + +
+ + +```jsx title="app/blog/[slug]/page.js" switcher +function generateStaticParams() {} + +export default function Page() { + return

Hello, Blog Post Page!

+} +``` + +
+
+ +> **Good to know**: フォルダ名を角括弧で囲む(例えば`[slug]`)と、特別な**dynamic route segment**が作成され、データから複数のページを生成するのに使用されます。これはブログ記事、製品ページなどに便利です。[dynamic segments](/docs/app/building-your-application/routing/dynamic-routes)についてもっと学びましょう。 + +### レイアウトをネストする {#nesting-layouts} + +デフォルトでは、フォルダ階層内のレイアウトはネストもされます。つまり、`children`プロップを介して子レイアウトをラップします。特定のルートセグメント(フォルダ)内に`layout`を追加することでレイアウトをネストできます。 + +たとえば、`/blog`ルートのレイアウトを作成するには、`blog`フォルダ内に新たに`layout`ファイルを追加します。 + +rootレイアウトがblogレイアウトをラッピングしているファイル階層 + + + + +```tsx title="app/blog/layout.tsx" switcher +export default function BlogLayout({ + children, +}: { + children: React.ReactNode +}) { + return
{children}
+} +``` + +
+ + +```jsx title="app/blog/layout.js" switcher +export default function BlogLayout({ children }) { + return
{children}
+} +``` + +
+
+ +上記の2つのレイアウトを組み合わせると、root レイアウト(`app/layout.js`)がblogレイアウト(`app/blog/layout.js`)をラップし、それがブログ(`app/blog/page.js`)とブログ投稿ページ(`app/blog/[slug]/page.js`)をラップします。 + +## ページ間をリンクする {#linking-between-pages} + +ルート間をナビゲートするために[``コンポーネント](/docs/app/api-reference/components/link)を使用できます。``は、HTML ``タグを拡張してプリフェッチングとクライアントサイドナビゲーションを提供する、組み込みのNext.jsコンポーネントです。 + +たとえば、ブログ記事のリストを生成するには、`next/link`から``をインポートし、コンポーネントに`href`プロップを渡します: + + + + +```tsx title="app/ui/post.tsx" highlight={1,6} switcher +import Link from 'next/link' + +export default async function Post({ post }) { + const posts = await getPosts() + + return ( +
    + {posts.map((post) => ( +
  • + {post.title} +
  • + ))} +
+ ) +} +``` + +
+ + +```jsx title="app/ui/post.js" highlight={1,6} switcher +import Link from 'next/link' + +export default async function Post({ post }) { + const posts = await getPosts() + + return ( +
    + {posts.map((post) => ( +
  • + {post.title} +
  • + ))} +
+ ) +} +``` + +
+
+ +``は、Next.jsアプリケーション内でルート間をナビゲートするための主要で推奨される方法です。ただし、[`useRouter`フック](/docs/app/api-reference/functions/use-router)を使用して、より高度なナビゲーションを行うこともできます。 diff --git a/docs/01-app/01-getting-started/02-project-structure.mdx b/docs/01-app/01-getting-started/03-project-structure.mdx similarity index 100% rename from docs/01-app/01-getting-started/02-project-structure.mdx rename to docs/01-app/01-getting-started/03-project-structure.mdx diff --git a/docs/01-app/02-building-your-application/01-routing/04-linking-and-navigating.mdx b/docs/01-app/02-building-your-application/01-routing/04-linking-and-navigating.mdx index 795afc3..742d72e 100644 --- a/docs/01-app/02-building-your-application/01-routing/04-linking-and-navigating.mdx +++ b/docs/01-app/02-building-your-application/01-routing/04-linking-and-navigating.mdx @@ -1,26 +1,26 @@ --- title: 'リンクとナビゲーション' -description: 'Next.jsにおけるナビゲーションの仕組みと、LinkコンポーネントとuseRouterフックの使用方法を学びます' +description: 'Next.jsでのナビゲーションの仕組みと、Linkコンポーネントと `useRouter` フックの使い方を学びます。' related: links: - 'app/building-your-application/caching' - 'app/api-reference/config/typescript' --- -Next.jsでは、ルート間をナビゲートする方法は4つあります: +Next.jsでルート間を移動する方法は4つあります: -- [`` コンポーネント](#link-component)を使用する +- [``コンポーネント](#link-component)を使用する - [`useRouter` フック](#userouter-hook)を使用する([Client Components](/docs/app/building-your-application/rendering/client-components)) - [`redirect` 関数](#redirect-function)を使用する([Server Components](/docs/app/building-your-application/rendering/server-components)) -- ネイティブな[History API](#using-the-native-history-api)を使用する +- ネイティブの[History API](#using-the-native-history-api)を使用する -このページでは、それぞれのオプションの使用方法について説明し、ナビゲーションの仕組みを詳しく見ていきます。 +このページでは、各オプションの使用方法を説明し、ナビゲーションの仕組みについて詳しく解説します。 -## `` コンポーネント {#link-component} +## ``コンポーネント {#link-component} -``は、HTMLの`
`タグを拡張し、[プリフェッチ](#2-prefetching)とクライアントサイドでのルート間ナビゲーションを提供する組み込みのコンポーネントです。Next.jsでルート間をナビゲートする主な推奨方法です。 +``コンポーネントは、HTMLの``タグを拡張し、[prefetching](#2-prefetching)とクライアントサイドのルート間のナビゲーションを提供します。これは、Next.jsで推奨されるルート間の移動方法です。 -`next/link`からインポートし、`href`プロップをコンポーネントに渡すことで使用できます: +このコンポーネントは、`next/link`からインポートし、`href`をプロップスとして渡して使用します: @@ -47,11 +47,11 @@ export default function Page() { -``に渡す他のオプションの`props`もあります。詳細は[APIリファレンス](/docs/app/api-reference/components/link)をご覧ください。 +``には他にもオプションのプロップスがあり、詳しくは[APIリファレンス](/docs/app/api-reference/components/link)をご覧ください。 -## `useRouter()` フック {#userouter-hook} +## `useRouter()`フック {#userouter-hook} -`useRouter`フックを使うと、[Client Components](/docs/app/building-your-application/rendering/client-components)からプログラム的にルートを変更できます。 +`useRouter`フックを使用すると、[Client Components](/docs/app/building-your-application/rendering/client-components)からプログラム的にルートを変更できます。 ```jsx title="app/page.js" 'use client' @@ -69,13 +69,13 @@ export default function Page() { } ``` -`useRouter`メソッドの完全なリストについては、[APIリファレンス](/docs/app/api-reference/functions/use-router)を参照してください。 +`useRouter`メソッドの全リストは[APIリファレンス](/docs/app/api-reference/functions/use-router)を参照してください。 -> **推奨事項:** 特定の要件がない限り、ルート間をナビゲートするためには``コンポーネントを使用してください。 +> **推奨:** `useRouter`を使用する特定の要件がある場合を除き、ルート間のナビゲーションには``コンポーネントを使用してください。 ## `redirect` 関数 {#redirect-function} -[Server Components](/docs/app/building-your-application/rendering/server-components)の場合、代わりに`redirect`関数を使用してください。 +[Server Components](/docs/app/building-your-application/rendering/server-components)では、`redirect`関数を使用します。 @@ -89,12 +89,21 @@ async function fetchTeam(id: string) { return res.json() } -export default async function Profile({ params }: { params: { id: string } }) { - const team = await fetchTeam(params.id) - if (!team) { +export default async function Profile({ + params, +}: { + params: Promise<{ id: string }> +}) { + const id = (await params).id + if (!id) { redirect('/login') } + const team = await fetchTeam(id) + if (!team) { + redirect('/join') + } + // ... } ``` @@ -112,11 +121,16 @@ async function fetchTeam(id) { } export default async function Profile({ params }) { - const team = await fetchTeam(params.id) - if (!team) { + const id = (await params).id + if (!id) { redirect('/login') } + const team = await fetchTeam(id) + if (!team) { + redirect('/join') + } + // ... } ``` @@ -124,25 +138,25 @@ export default async function Profile({ params }) { -> **知っておいてよい点**: +> **Good to know:** > -> - `redirect`はデフォルトで307(Temporary Redirect)ステータスコードを返します。サーバーアクションで使用した場合、303(See Other)を返します。これは、POSTリクエストの結果として成功ページにリダイレクトする際によく使用されます。 -> - `redirect`は内部的にエラーを投げるので、`try/catch`ブロックの外で呼び出されるべきです。 -> - `redirect`はクライアントコンポーネントでのレンダリングプロセス中に呼び出せますが、イベントハンドラ内では使用できません。代わりに[`useRouter`フック](#userouter-hook)を使用できます。 -> - `redirect`は絶対URLも受け入れ、外部リンクにリダイレクトするために使用できます。 -> - レンダープロセスの前にリダイレクトしたい場合は、[`next.config.js`](/docs/app/building-your-application/routing/redirecting#redirects-in-nextconfigjs)や[ミドルウェア](/docs/app/building-your-application/routing/redirecting#nextresponseredirect-in-middleware)を使用してください。 +> - `redirect`は、デフォルトで307(Temporary Redirect)ステータスコードを返します。Server Actionで使用すると、POSTリクエストの結果としてよく使用される303(See Other)を返します。 +> - `redirect`は内部的にエラーをスローするため、`try/catch`ブロックの外側で呼び出す必要があります。 +> - `redirect`はレンダリングプロセス中にClient Componentsで呼び出すことができますが、イベントハンドラ内では使用できません。代わりに[`useRouter` フック](#userouter-hook)を使用できます。 +> - `redirect`は絶対URLも受け入れ、外部リンクへのリダイレクトに使用できます。 +> - レンダリングプロセスの前にリダイレクトしたい場合は、[`next.config.js`](/docs/app/building-your-application/routing/redirecting#redirects-in-nextconfigjs)または[Middleware](/docs/app/building-your-application/routing/redirecting#nextresponseredirect-in-middleware)を使用してください。 -より詳しい情報は、[`redirect` APIリファレンス](/docs/app/api-reference/functions/redirect)を参照してください。 +詳細は[`redirect` APIリファレンス](/docs/app/api-reference/functions/redirect)をご覧ください。 -## ネイティブなHistory APIを使用する {#using-the-native-history-api} +## ネイティブHistory APIの使用 {#using-the-native-history-api} -Next.jsでは、ネイティブの[`window.history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)と[`window.history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState)メソッドを使用して、ページをリロードせずにブラウザの履歴スタックを更新することができます。 +Next.jsでは、ブラウザの履歴スタックをページを再読み込みせずに更新するために、ネイティブの[`window.history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)と[`window.history.replaceState`](https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState)メソッドを使用できます。 -`pushState`と`replaceState`の呼び出しはNext.js Routerと統合され、[`usePathname`](/docs/app/api-reference/functions/use-pathname)と[`useSearchParams`](/docs/app/api-reference/functions/use-search-params)と同期できます。 +`pushState`と`replaceState`の呼び出しはNext.js Routerに統合され、[`usePathname`](/docs/app/api-reference/functions/use-pathname)や[`useSearchParams`](/docs/app/api-reference/functions/use-search-params)と同期することができます。 ### `window.history.pushState` {#window-history-pushstate} -ブラウザの履歴スタックに新しいエントリを追加するために使用します。ユーザーは前の状態に戻ることができます。例えば、製品リストをソートするには: +ブ​​ラウザの履歴スタックに新しいエントリを追加するために使用します。ユーザーは前の状態に戻ることができます。例えば、商品のリストをソートする場合: @@ -201,7 +215,7 @@ export default function SortProducts() { ### `window.history.replaceState` {#window-history-replacestate} -ブラウザの履歴スタックの現在のエントリを置き換えるために使用します。ユーザーは前の状態に戻ることができません。例えば、アプリケーションのロケールを切り替えるには: +ブラウザの履歴スタックの現在のエントリを置き換えるために使用します。ユーザーは前の状態に戻ることができません。例えば、アプリケーションのロケールを切り替える場合: @@ -260,67 +274,67 @@ export function LocaleSwitcher() { ## ルーティングとナビゲーションの仕組み {#how-routing-and-navigation-works} -App Routerは、ルーティングとナビゲーションにハイブリッドアプローチを採用しています。サーバー上では、アプリケーションコードがルートセグメントによって自動的に[コード分割](#1-code-splitting)され、クライアント側では、Next.jsがルートセグメントを[プリフェッチ](#2-prefetching)し[キャッシュ](#3-caching)します。つまり、ユーザーが新しいルートに移動しても、ブラウザはページをリロードせず、変更されたルートセグメントだけが再レンダリングされます。これにより、ナビゲーション体験とパフォーマンスが向上します。 +App Routerはハイブリッドアプローチでルーティングとナビゲーションを行います。サーバー上で、アプリケーションコードはルートセグメントごとに自動で[コード分割](#1-code-splitting)されます。そしてクライアントでは、Next.jsがルートセグメントを[prefetch](#2-prefetching)し、[キャッシュ](#3-caching)します。これにより、ユーザーが新しいルートに移動するときにブラウザがページを再読み込みせず、変更されたルートセグメントのみが再レンダリングされるため、ナビゲーションの体験とパフォーマンスが向上します。 ### 1. コード分割 {#1-code-splitting} -コード分割により、アプリケーションコードを小さなバンドルに分割し、ブラウザでダウンロードおよび実行できるようになります。これにより、データ転送量と各リクエストの実行時間が短縮され、パフォーマンスが向上します。 +コード分割は、アプリケーションコードをブラウザでダウンロードおよび実行する小さなバンドルに分割することです。これにより、各リクエストのデータ転送量と実行時間を減らし、パフォーマンスが向上します。 -[Server Components](/docs/app/building-your-application/rendering/server-components)により、アプリケーションコードはルートセグメントによって自動的にコード分割されます。これにより、ナビゲーション時には現在のルートに必要なコードのみが読み込まれます。 +[Server Components](/docs/app/building-your-application/rendering/server-components)により、アプリケーションコードはルートセグメントで自動的にコード分割されます。これにより、ナビゲーション時に現在のルートに必要なコードのみがロードされます。 ### 2. プリフェッチ {#2-prefetching} -プリフェッチは、ユーザーが訪問する前にバックグラウンドでルートを事前にロードする方法です。 +プリフェッチは、ユーザーがアクセスする前にルートをバックグラウンドで事前ロードする方法です。 -Next.jsではルートがプリフェッチされる方法は2つあります: +Next.jsでのルートプリフェッチには2つの方法があります: -- **`` コンポーネント**:ユーザーのビューポートに表示されると、ルートは自動的にプリフェッチされます。プリフェッチは、ページが最初にロードされるときや、スクロールによってビューに入るときに行われます。 -- **`router.prefetch()`**:`useRouter`フックを使用して、プログラム的にルートをプリフェッチできます。 +- **``コンポーネント**:ユーザーのビューポートに表示されると、ルートが自動でプリフェッチされます。プリフェッチは、ページが最初にロードされるときや、スクロールによって表示されるときに行われます。 +- **`router.prefetch()`**:`useRouter`フックを用いてプログラム的にルートをプリフェッチすることができます。 -``のデフォルトのプリフェッチ動作(つまり、`prefetch`プロップが未指定または`null`に設定されている場合)は、[`loading.js`](/docs/app/api-reference/file-conventions/loading)の使用に応じて異なります。共有レイアウトのみがプリフェッチされ、「コンポーネントのツリー」がレンダリングされる最初の`loading.js`ファイルまでキャッシュされます。これにより、動的ルート全体をフェッチするコストが削減され、即時の[ローディング状態](/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states)がユーザーにより良い視覚的フィードバックを提供します。 +``のデフォルトのプリフェッチ動作(`prefetch`プロップスが未指定または`null`の場合)は、[`loading.js`](/docs/app/api-reference/file-conventions/loading)の使用状況に応じて異なります。表示されているコンポーネントの"tree"上の共有レイアウトまでが、この`loading.js`ファイルより下まで30秒間プリフェッチされ、キャッシュされます。これにより、完全な動的ルートをフェッチするコストが削減され、ユーザーへの[インスタントローディングステート](/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states)の表示によるより良い視覚的フィードバックが提供されます。 -プリフェッチを無効にするには、`prefetch`プロップを`false`に設定します。あるいは、`prefetch`プロップを`true`に設定して、ローディングの境界を超えて完全なページデータをプリフェッチすることができます。 +プリフェッチを無効にするには、`prefetch`プロップスを`false`に設定します。代わりに、ローディング境界を超えた完全なページデータをプリフェッチするには、`prefetch`プロップスを`true`に設定します。 -詳細は[`` APIリファレンス](/docs/app/api-reference/components/link)を参照してください。 +詳しくは[`` APIリファレンス](/docs/app/api-reference/components/link)を参照してください。 -> **知っておいてよい点**: +> **Good to know:** > -> - プリフェッチは開発環境では有効ではなく、本番環境でのみ有効です。 +> - プリフェッチは開発環境では有効ではなく、プロダクションのみに有効です。 ### 3. キャッシュ {#3-caching} -Next.jsには**インメモリーのクライアントサイドキャッシュ**があり、[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)と呼ばれます。ユーザーがアプリをナビゲートすると、[プリフェッチされた](#2-prefetching)ルートセグメントと訪問したルートのReactサーバーコンポーネントペイロードがキャッシュに保存されます。 +Next.jsには、**メモリ内クライアントサイドキャッシュ**として[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)があります。ユーザーがアプリをナビゲートする際に、[prefetched](#2-prefetching)されたルートセグメントと訪問されたルートのReact Server Componentのペイロードがキャッシュに保存されます。 -つまり、ナビゲーション時には、可能な限りキャッシュが再利用され、新たなサーバーへのリクエストを行う代わりに、キャッシュが使用されます。これにより、リクエスト数とデータ転送量が削減され、パフォーマンスが向上します。 +これにより、ナビゲーション時には可能な限りキャッシュが再利用され、新たなサーバーリクエストを行う代わりに、リクエスト数と転送されるデータ量が削減され、パフォーマンスが向上します。 -[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)の仕組みと構成方法についての詳細をご覧ください。 +[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)の動作、設定方法について詳しく学ぶことができます。 -### 4. 部分的なレンダリング {#4-partial-rendering} +### 4. 部分的レンダリング {#4-partial-rendering} -部分的なレンダリングとは、クライアント上のナビゲーションで変更されるルートセグメントのみが再レンダリングされ、共有セグメントは保持されることを意味します。 +部分的レンダリングにより、ナビゲーション時に変更されるルートセグメントのみがクライアントで再レンダリングされ、共有セグメントは保持されます。 -たとえば、2つの兄弟ルート`/dashboard/settings`と`/dashboard/analytics`間を移動する際には、`settings`ページがアンマウントされ、`analytics`ページが新しい状態でマウントされ、共有の`dashboard`レイアウトが保存されます。この動作は、同じ動的セグメント上の2つのルート間でも発生します。たとえば、`/blog/[slug]/page`および`/blog/first`から`/blog/second`へのナビゲーション時です。 +例えば、2つの兄弟ルート`/dashboard/settings`と`/dashboard/analytics`間を移動する際、`settings`ページはアンマウントされ、`analytics`ページは新しい状態でマウントされ、共有の`dashboard`レイアウトは保持されます。この動作は、`/blog/[slug]/page`と`/blog/first`から`/blog/second`への移動のような同じ動的セグメント内の2つのルート間でも発生します。 部分的なレンダリングの仕組み -部分的なレンダリングがない場合、各ナビゲーションはクライアントですべてのページを再レンダリングさせます。変更されるセグメントのみをレンダリングすることで、データ転送量と実行時間が削減され、パフォーマンスが向上します。 +部分的レンダリングがない場合、各ナビゲーションでページ全体がクライアントで再レンダリングされます。変更されたセグメントのみをレンダリングすることで、転送データ量と実行時間が削減され、パフォーマンスが向上します。 ### 5. ソフトナビゲーション {#5-soft-navigation} -ブラウザはページ間のナビゲーションで「ハードナビゲーション」を行います。Next.jsのApp Routerは、ページ間での「ソフトナビゲーション」を可能にし、変更されたルートセグメントのみが再レンダリングされるようにします(部分的なレンダリング)。これにより、クライアントのReact stateがナビゲーション中に保存されます。 +ブラウザはページ間を移動する際に「ハードナビゲーション」を行います。Next.jsのApp Routerは、ページ間の「ソフトナビゲーション」を有効にし、変更されたルートセグメントのみが再レンダリングされるようにします(部分的レンダリング)。これにより、ナビゲーション中にクライアントのReact状態が保持されます。 -### 6. 前後のナビゲーション {#6-back-and-forward-navigation} +### 6. 戻ると進むナビゲーション {#6-back-and-forward-navigation} -デフォルトでは、Next.jsは前後のナビゲーションでスクロール位置を維持し、[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)のルートセグメントを再利用します。 +デフォルトでは、Next.jsは後方と前方へのナビゲーションの際にスクロール位置を維持し、[Router Cache](/docs/app/building-your-application/caching#client-side-router-cache)でルートセグメントを再利用します。 ### 7. `pages/`と`app/`間のルーティング {#7-routing-between-pages-and-app} -`pages/`から`app/`へのインクリメンタル移行時に、Next.jsルーターは両者間のハードナビゲーションを自動的に処理します。`pages/`から`app/`への移行を検出するために、アプリルートの確率的チェックを活用したクライアントルーターフィルターがありますが、これは稀に偽陽性を引き起こす可能性があります。通常、こうした事例は非常に稀ですが、偽陽性の確率は0.01%に設定されています。この確率は、`next.config.js`の`experimental.clientRouterFilterAllowedRate`オプションを通じてカスタマイズできます。偽陽性率を下げると、クライアントバンドル内の生成されたフィルターのサイズが増加することに注意してください。 +`pages/`から`app/`へのインクリメンタルな移行時、Next.jsのルーターは自動でその間のハードナビゲーションを処理します。`pages/`から`app/`への遷移を検出するために、クライアントルーターのフィルターがアプリルートの確率的チェックを活用し、時折の偽陽性を生じる可能性があります。既定では、発生頻度は非常にまれであり、その発生率は0.01%に設定されています。この発生率は`next.config.js`の`experimental.clientRouterFilterAllowedRate`オプションでカスタマイズ可能です。発生率を下げると、クライアントバンドルで生成されたフィルターのサイズが増加します。 -完全にこの処理を無効にして、`pages/`と`app/`間のルーティングを手動で管理したい場合は、`next.config.js`で`experimental.clientRouterFilter`を`false`に設定できます。この機能が無効化されると、appルートと重なるページの動的ルートがデフォルトでは正しくナビゲートされません。 +また、`pages/`と`app/`間のルーティングを完全に無効にし、その管理を手動で行いたい場合、`next.config.js`で`experimental.clientRouterFilter`をfalseに設定できます。この機能が無効な場合、ページ内の動的ルートがアプリのルートと重複していると、そのルートには正しくナビゲートされません。 diff --git a/docs/01-app/02-building-your-application/01-routing/07-redirecting.mdx b/docs/01-app/02-building-your-application/01-routing/07-redirecting.mdx index 8fe8461..7c649a8 100644 --- a/docs/01-app/02-building-your-application/01-routing/07-redirecting.mdx +++ b/docs/01-app/02-building-your-application/01-routing/07-redirecting.mdx @@ -1,6 +1,6 @@ --- -title: 'リダイレクト' -description: 'Next.jsでリダイレクトを処理するさまざまな方法を学びます。' +title: 'Redirecting' +description: 'Next.jsでリダイレクトを処理するさまざまな方法について学びます。' related: links: - 'app/api-reference/functions/redirect' @@ -9,27 +9,27 @@ related: - 'app/api-reference/config/next-config-js/redirects' --- -Next.jsでリダイレクトを処理する方法はいくつかあります。このページでは、利用可能な各オプション、ユースケース、および大量のリダイレクトを管理する方法について説明します。 +Next.jsでは、リダイレクトを処理するいくつかの方法があります。このページでは、利用可能な各オプション、使用事例、および大量のリダイレクトを管理する方法について説明します。 -| API | 目的 | 使用場所 | ステータスコード | -| -------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------- | ----------------------------------- | -| [`redirect`](#redirect-function) | ミューテーションまたはイベント後にユーザーをリダイレクトする | Server Components、Server Actions、Route Handlers | 307(仮)または303(Server Action) | -| [`permanentRedirect`](#permanentredirect-function) | ミューテーションまたはイベント後にユーザーをリダイレクトする | Server Components、Server Actions、Route Handlers | 308(永続) | -| [`useRouter`](#userouter-hook) | クライアントサイドのナビゲーションを実行する | Client Componentsのイベントハンドラーで | 該当なし | -| [`next.config.js`内の`redirects`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js`ファイル | 307(仮)または308(永続) | -| [`NextResponse.redirect`](#nextresponseredirect-in-middleware) | 条件に基づいて受信リクエストをリダイレクトする | ミドルウェア | 任意 | +| API | 目的 | 使用場所 | ステータスコード | +| -------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------- | --------------------------------------- | +| [`redirect`](#redirect-function) | ミューテーションまたはイベント後にユーザーをリダイレクトする | Server Components、Server Actions、Route Handlers | 307 (一時的) または 303 (Server Action) | +| [`permanentRedirect`](#permanentredirect-function) | ミューテーションまたはイベント後にユーザーをリダイレクトする | Server Components、Server Actions、Route Handlers | 308 (永続) | +| [`useRouter`](#userouter-hook) | クライアント側でのナビゲーションを実行する | Client Components のイベントハンドラ | N/A | +| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js` ファイル | 307 (一時的) または 308 (永続的) | +| [`NextResponse.redirect`](#nextresponseredirect-in-middleware) | 条件に基づいて受信リクエストをリダイレクトする | Middleware | 任意 | -| API | 目的 | 使用場所 | ステータスコード | -| -------------------------------------------------------------- | ---------------------------------------------- | ------------------------ | -------------------------- | -| [`useRouter`](#userouter-hook) | クライアントサイドのナビゲーションを実行する | コンポーネント | 該当なし | -| [`next.config.js`内の`redirects`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js`ファイル | 307(仮)または308(永続) | -| [`NextResponse.redirect`](#nextresponseredirect-in-middleware) | 条件に基づいて受信リクエストをリダイレクトする | ミドルウェア | 任意 | +| API | 目的 | 使用場所 | ステータスコード | +| -------------------------------------------------------------- | ---------------------------------------------- | ------------------------- | -------------------------------- | +| [`useRouter`](#userouter-hook) | クライアント側でのナビゲーションを実行する | Components | N/A | +| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js` ファイル | 307 (一時的) または 308 (永続的) | +| [`NextResponse.redirect`](#nextresponseredirect-in-middleware) | 条件に基づいて受信リクエストをリダイレクトする | Middleware | 任意 | @@ -37,14 +37,14 @@ Next.jsでリダイレクトを処理する方法はいくつかあります。 ## `redirect` 関数 {#redirect-function} -`redirect` 関数を使用すると、ユーザーを別のURLにリダイレクトすることができます。`redirect`を[Server Components](/docs/app/building-your-application/rendering/server-components)、[Route Handlers](/docs/app/building-your-application/routing/route-handlers)、および[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で呼び出すことができます。 +`redirect` 関数を使用すると、他の URL にユーザーをリダイレクトすることができます。 `redirect` は[Server Components](/docs/app/building-your-application/rendering/server-components)、[Route Handlers](/docs/app/building-your-application/routing/route-handlers)、および[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で呼び出すことができます。 -`redirect`は、ミューテーションまたはイベントの後によく使用されます。たとえば、投稿を作成する場合です: +`redirect` はミューテーションまたはイベントの後によく使用されます。たとえば、投稿を作成する場合: - + -```tsx title="app/actions.tsx" switcher +```ts title="app/actions.ts" switcher 'use server' import { redirect } from 'next/navigation' @@ -63,9 +63,9 @@ export async function createPost(id: string) { ``` - + -```jsx title="app/actions.js" switcher +```js title="app/actions.js" switcher 'use server' import { redirect } from 'next/navigation' @@ -86,26 +86,26 @@ export async function createPost(id) { -> **参考情報**: +> **Good to know**: > -> - `redirect`はデフォルトで307(Temporary Redirect)ステータスコードを返します。Server Actionで使用されるとき、通常はPOSTリクエストの結果として成功ページにリダイレクトするために使用される303(See Other)を返します。 -> - `redirect`は内部でエラーをスローするため、`try/catch`ブロックの外で呼び出す必要があります。 -> - `redirect`はクライアントコンポーネントのレンダリングプロセス中に呼び出すことができますが、イベントハンドラーでは呼び出せません。[`useRouter`フック](#userouter-hook)を代わりに使用できます。 -> - `redirect`は絶対URLも受け入れ、外部リンクにリダイレクトするために使用できます。 -> - レンダープロセスの前にリダイレクトしたい場合は、[`next.config.js`](#redirects-in-nextconfigjs)または[Middleware](#nextresponseredirect-in-middleware)を使用してください。 +> - `redirect` はデフォルトで 307 (一時的リダイレクト) ステータスコードを返します。Server Action で使用される場合、POST リクエストの結果として成功ページにリダイレクトする際によく使用される 303 (他を参照せよ) を返します。 +> - `redirect` は内部でエラーをスローするため、`try/catch` ブロックの外で呼び出す必要があります。 +> - `redirect` はClient Componentsのレンダリングプロセス中に呼び出すことができますが、イベントハンドラ内では呼び出せません。代わりに、[`useRouter` フック](#userouter-hook)を使用できます。 +> - `redirect` は絶対 URL も受け入れ、外部リンクにリダイレクトするために使用することができます。 +> - レンダリングプロセスの前にリダイレクトしたい場合は [`next.config.js`](#redirects-in-nextconfigjs) または [Middleware](#nextresponseredirect-in-middleware) を使用してください。 -[`redirect` APIリファレンス](/docs/app/api-reference/functions/redirect)を参照して、さらに情報をご覧ください。 +[`redirect` API リファレンス](/docs/app/api-reference/functions/redirect)を参照してください。 ## `permanentRedirect` 関数 {#permanentredirect-function} -`permanentRedirect` 関数は、ユーザーを別のURLに**永久に**リダイレクトすることができます。`permanentRedirect`を[Server Components](/docs/app/building-your-application/rendering/server-components)、[Route Handlers](/docs/app/building-your-application/routing/route-handlers)、および[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で呼び出すことができます。 +`permanentRedirect` 関数は、ユーザーを別の URL に**永続的に**リダイレクトさせることができます。 `permanentRedirect` は[Server Components](/docs/app/building-your-application/rendering/server-components)、[Route Handlers](/docs/app/building-your-application/routing/route-handlers)、および[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で呼び出すことができます。 -`permanentRedirect`は、エンティティの正規URLが変更されるミューテーションまたはイベントの後によく使用されます。たとえば、ユーザーがユーザー名を変更した後にプロフィールURLを更新する場合です: +`permanentRedirect` は、エンティティの標準 URL が変更された後によく使用されます。たとえば、ユーザーがユーザー名を変更した後にユーザープロフィール URL を更新する場合など: - + -```tsx title="app/actions.ts" switcher +```ts title="app/actions.ts" switcher 'use server' import { permanentRedirect } from 'next/navigation' @@ -118,15 +118,15 @@ export async function updateUsername(username: string, formData: FormData) { // エラーを処理する } - revalidateTag('username') // ユーザー名のすべての参照を更新する + revalidateTag('username') // ユーザー名へのすべての参照を更新する permanentRedirect(`/profile/${username}`) // 新しいユーザープロフィールに移動する } ``` - + -```jsx title="app/actions.js" switcher +```js title="app/actions.js" switcher 'use server' import { permanentRedirect } from 'next/navigation' @@ -139,7 +139,7 @@ export async function updateUsername(username, formData) { // エラーを処理する } - revalidateTag('username') // ユーザー名のすべての参照を更新する + revalidateTag('username') // ユーザー名へのすべての参照を更新する permanentRedirect(`/profile/${username}`) // 新しいユーザープロフィールに移動する } ``` @@ -147,13 +147,13 @@ export async function updateUsername(username, formData) { -> **参考情報**: +> **Good to know**: > -> - `permanentRedirect`はデフォルトで308(恒久的リダイレクト)ステータスコードを返します; -> - `permanentRedirect`は絶対URLも受け入れ、外部リンクにリダイレクトするために使用できます; -> - レンダープロセスの前にリダイレクトしたい場合は、[`next.config.js`](#redirects-in-nextconfigjs)または[Middleware](#nextresponseredirect-in-middleware)を使用してください; +> - `permanentRedirect` はデフォルトで 308 (永続的リダイレクト) ステータスコードを返します。 +> - `permanentRedirect` は絶対 URL も受け入れ、外部リンクにリダイレクトするために使用することができます。 +> - レンダリングプロセスの前にリダイレクトしたい場合は [`next.config.js`](#redirects-in-nextconfigjs) または [Middleware](#nextresponseredirect-in-middleware) を使用してください。 -[`permanentRedirect` APIリファレンス](/docs/app/api-reference/functions/permanentRedirect)を参照して、さらに情報をご覧ください。 +[`permanentRedirect` API リファレンス](/docs/app/api-reference/functions/permanentRedirect)を参照してください。 @@ -161,7 +161,7 @@ export async function updateUsername(username, formData) { -クライアントコンポーネントのイベントハンドラー内でリダイレクトが必要な場合、`useRouter`フックの`push`メソッドを使用できます。例えば: +Client Component内のイベントハンドラ内でリダイレクトが必要な場合は、`useRouter` フックの `push` メソッドを使用できます。たとえば: @@ -208,7 +208,7 @@ export default function Page() { -コンポーネント内でリダイレクトする必要がある場合、`useRouter`フックの`push`メソッドを使用できます。例えば: +コンポーネント内でリダイレクトが必要な場合は、`useRouter` フックの `push` メソッドを使用できます。たとえば: @@ -249,29 +249,29 @@ export default function Page() { -> **参考情報**: +> **Good to know**: > -> - プログラムでユーザーをナビゲートする必要がない場合は、[``](/docs/app/api-reference/components/link)コンポーネントを使用するべきです。 +> - プログラムによってユーザーを移動させる必要がない場合、[``](/docs/app/api-reference/components/link) コンポーネントを使用するべきです。 -[`useRouter` APIリファレンス](/docs/app/api-reference/functions/use-router)を参照して、さらに情報をご覧ください。 +[`useRouter` API リファレンス](/docs/app/api-reference/functions/use-router)を参照してください。 -[`useRouter` APIリファレンス](https://nextjs.org/docs/canary/pages/api-reference/functions/use-router)を参照して、さらに情報をご覧ください。 +[`useRouter` API リファレンス](https://nextjs.org/docs/canary/pages/api-reference/functions/use-router)を参照してください。 -## `next.config.js`内の`redirects` {#redirects-in-next-config-js} +## `next.config.js` の中の `redirects` {#redirects-in-next-config-js} -`next.config.js`ファイル内の`redirects`オプションを使用すると、受信リクエストのパスを別の宛先パスにリダイレクトできます。これは、ページのURL構造を変更した場合や、事前に既知のリダイレクトのリストがある場合に便利です。 +`next.config.js` ファイル内の `redirects` オプションを使用すると、受信リクエストのパスを別の宛先パスにリダイレクトできます。これは、ページの URL 構造を変更した場合や、事前にわかっているリダイレクトのリストを持っている場合に便利です。 -`redirects`は、[パス](/docs/app/api-reference/config/next-config-js/redirects#path-matching)、[ヘッダー、cookie、クエリのマッチング](/docs/app/api-reference/config/next-config-js/redirects#header-cookie-and-query-matching)をサポートし、受信リクエストに基づいてユーザーをリダイレクトする柔軟性を提供します。 +`redirects` は [パス](/docs/app/api-reference/config/next-config-js/redirects#path-matching)、[ヘッダ、cookie、クエリのマッチング](/docs/app/api-reference/config/next-config-js/redirects#header-cookie-and-query-matching) をサポートしており、受信リクエストに基づいてユーザーをリダイレクトする柔軟性を提供します。 -`redirects`を使用するには、`next.config.js`ファイルにオプションを追加します: +`redirects` を使用するには、`next.config.js` ファイルにオプションを追加します: ```js title="next.config.js" module.exports = { @@ -294,36 +294,36 @@ module.exports = { } ``` -[`redirects` APIリファレンス](/docs/app/api-reference/config/next-config-js/redirects)を参照して、さらに情報をご覧ください。 +[`redirects` API リファレンス](/docs/app/api-reference/config/next-config-js/redirects)を参照してください。 -> **参考情報**: +> **Good to know**: > -> - `redirects`は、`permanent`オプションを使用して307(Temporary Redirect)または308(Permanent Redirect)ステータスコードを返すことができます; -> - プラットフォームによっては、`redirects`に制限がある場合があります。たとえば、Vercelでは1,024件のリダイレクトの制限があります。大量のリダイレクト(1000件以上)を管理するには、[Middleware](/docs/app/building-your-application/routing/middleware)を使用したカスタムソリューションを作成することを検討してください。規模に応じたリダイレクト管理については、[managing redirects at scale](#managing-redirects-at-scale-advanced)を参照してください; -> - `redirects`はミドルウェアの**前に**実行されます; +> - `redirects` は `permanent` オプションとともに 307 (一時的リダイレクト) または 308 (永続的リダイレクト) ステータスコードを返すことができます。 +> - `redirects` はプラットフォームに制限がある場合があります。たとえば、Vercel では 1,024 のリダイレクト制限があります。1000 件以上の大量のリダイレクトを管理するには、[Middleware](/docs/app/building-your-application/routing/middleware) を使用してカスタムソリューションを作成することを検討してください。詳細については、[大規模なリダイレクトの管理](#managing-redirects-at-scale-advanced)を参照してください。 +> - `redirects` は Middleware **前**に実行されます。 -## `NextResponse.redirect` in Middleware {#nextresponse-redirect-in-middleware} +## Middleware の `NextResponse.redirect` {#nextresponse-redirect-in-middleware} -ミドルウェアを使用すると、リクエストが完了する前にコードを実行できます。そして、受信リクエストに基づいて`NextResponse.redirect`を使用して別のURLにリダイレクトします。これは、条件(例:認証、セッション管理など)に基づいてユーザーをリダイレクトする場合や、大量のリダイレクトがあります: +Middleware を使用すると、リクエストが完了する前にコードを実行できます。次に、受信リクエストに基づいて `NextResponse.redirect` を使用して異なる URL にリダイレクトします。これは、条件に基づいてユーザーをリダイレクトしたい場合(例: 認証、セッション管理など)や[大量のリダイレクト](#managing-redirects-at-scale-advanced)を持っている場合に便利です。 -たとえば、ユーザーが認証されていない場合に`/login`ページにリダイレクトするには: +たとえば、ユーザーが認証されていない場合に `/login` ページにリダイレクトするには: - + -```tsx title="middleware.ts" switcher +```ts title="middleware.ts" switcher import { NextResponse, NextRequest } from 'next/server' import { authenticate } from 'auth-provider' export function middleware(request: NextRequest) { const isAuthenticated = authenticate(request) - // ユーザーが認証されている場合は、通常通り続行します + // ユーザーが認証されている場合は通常通りに継続する if (isAuthenticated) { return NextResponse.next() } - // 認証されていない場合は、ログインページにリダイレクトします + // 認証されていない場合はログインページにリダイレクトする return NextResponse.redirect(new URL('/login', request.url)) } @@ -342,12 +342,12 @@ import { authenticate } from 'auth-provider' export function middleware(request) { const isAuthenticated = authenticate(request) - // ユーザーが認証されている場合は、通常通り続行します + // ユーザーが認証されている場合は通常通りに継続する if (isAuthenticated) { return NextResponse.next() } - // 認証されていない場合は、ログインページにリダイレクトします + // 認証されていない場合はログインページにリダイレクトする return NextResponse.redirect(new URL('/login', request.url)) } @@ -359,26 +359,26 @@ export const config = { -> **参考情報**: +> **Good to know**: > -> - ミドルウェアは、`next.config.js`の`redirects`**後に**実行され、レンダリングの**前に**実行されます; +> - Middleware は `next.config.js` 内の `redirects` の**後**、レンダリングの**前**に実行されます。 -[Middleware](/docs/app/building-your-application/routing/middleware)のドキュメントを参照して、さらに情報をご覧ください。 +[Middleware](/docs/app/building-your-application/routing/middleware) のドキュメントを参照してください。 -## 規模に応じたリダイレクト管理(高度) {#managing-redirects-at-scale-advanced} +## 大規模なリダイレクトの管理 (高度な) {#managing-redirects-at-scale-advanced} -大量のリダイレクト(1000件以上)を管理するために、ミドルウェアを使用してカスタムソリューションを作成することを検討してください。これにより、アプリケーションを再デプロイすることなく、プログラムでリダイレクトを処理できます。 +大量のリダイレクト(1000 件以上)を管理するには、Middleware を使用してカスタムソリューションを作成することを検討できます。これにより、アプリケーションを再デプロイすることなくプログラム的にリダイレクトを処理できます。 -これを行うには、以下を考慮する必要があります: +これを行うには、次のことを考慮する必要があります: -1. リダイレクトマップの作成と保存 -2. データ検索パフォーマンスの最適化 +1. リダイレクトマップを作成し、格納すること。 +2. データ検索パフォーマンスを最適化すること。 -> **Next.jsの例**:以下の推奨事項の実装については、[Middleware with Bloom filter](https://redirects-bloom-filter.vercel.app/)の例を参照してください。 +> **Next.js の例**:以下の推奨事項を実装するための[Middleware with Bloom filter](https://redirects-bloom-filter.vercel.app/) の例を参照してください。 -### 1. リダイレクトマップの作成と保存 {#1-creating-and-storing-a-redirect-map} +### 1. リダイレクトマップを作成し、格納すること {#1-creating-and-storing-a-redirect-map} -リダイレクトマップは、データベース(通常はキー・バリュー・ストア)またはJSONファイルに保存できるリダイレクトのリストです。 +リダイレクトマップは、データベース(通常はキーと値のストア)または JSON ファイルに格納できるリダイレクトのリストです。 次のデータ構造を考慮してください: @@ -395,12 +395,12 @@ export const config = { } ``` -[Middleware](/docs/app/building-your-application/routing/middleware)で、Vercelの[Edge Config](https://vercel.com/docs/storage/edge-config/get-started?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)や[Redis](https://vercel.com/docs/storage/vercel-kv?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)などのデータベースから読み取り、受信リクエストに基づいてユーザーをリダイレクトすることができます: +[Middleware](/docs/app/building-your-application/routing/middleware)では、Vercel の[Edge Config](https://vercel.com/docs/storage/edge-config/get-started?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)や[Redis](https://vercel.com/docs/storage/vercel-kv?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)などのデータベースから読み取り、受信リクエストに基づいてユーザーをリダイレクトできます: - + -```tsx title="middleware.ts" switcher +```ts title="middleware.ts" switcher import { NextResponse, NextRequest } from 'next/server' import { get } from '@vercel/edge-config' @@ -419,7 +419,7 @@ export async function middleware(request: NextRequest) { return NextResponse.redirect(redirectEntry.destination, statusCode) } - // リダイレクトが見つからなかった場合、そのまま継続します + // リダイレクトが見つからなかった場合はリダイレクトなしで続行する return NextResponse.next() } ``` @@ -441,7 +441,7 @@ export async function middleware(request) { return NextResponse.redirect(redirectEntry.destination, statusCode) } - // リダイレクトが見つからなかった場合、そのまま継続します + // リダイレクトが見つからなかった場合はリダイレクトなしで続行する return NextResponse.next() } ``` @@ -449,21 +449,21 @@ export async function middleware(request) { -### 2. データ検索パフォーマンスの最適化 {#2-optimizing-data-lookup-performance} +### 2. データ検索パフォーマンスを最適化すること {#2-optimizing-data-lookup-performance} -大規模データセットをすべての受信リクエストのために読み取ることは遅く、費用がかかります。データ検索パフォーマンスを最適化する方法は2つあります: +受信毎のリクエストに対して大容量データを読むことは、遅く、費用がかかる場合があります。データ検索パフォーマンスを最適化するには2つの方法があります: -- [Vercel Edge Config](https://vercel.com/docs/storage/edge-config/get-started?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)や[Redis](https://vercel.com/docs/storage/vercel-kv?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)などの、高速読み取りに最適化されたデータベースを使用します; -- [ブルームフィルター](https://en.wikipedia.org/wiki/Bloom_filter)のようなデータ検索戦略を使用して、リダイレクトが存在するかどうかを効率的にチェックし、より大きなリダイレクトファイルやデータベースを読み取る**前に**行います; +- [Vercel Edge Config](https://vercel.com/docs/storage/edge-config/get-started?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)や[Redis](https://vercel.com/docs/storage/vercel-kv?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)など、速い読み取りに最適化されたデータベースを使用する +- [ブルームフィルタ](https://en.wikipedia.org/wiki/Bloom_filter)のようなデータ検索戦略を使用して、より大きなリダイレクトファイルやデータベースを読む前にリダイレクトが存在するかどうかを効率的に確認する -前述の例では、生成されたブルームフィルターファイルをミドルウェアにインポートし、受信リクエストのパス名がブルームフィルターに存在するかどうかを確認します。 +前述の例を考慮し、ブルームフィルタファイルを Middleware にインポートし、受信リクエストのパスがブルームフィルタに存在するかどうかを確認することができます。 -存在する場合は、要求を[API Routes](https://nextjs.org/docs/canary/pages/building-your-application/routing/api-routes) [Route Handler](/docs/app/building-your-application/routing/route-handlers)に転送し、要求が実際に存在するかをチェックし、ユーザーを適切なURLにリダイレクトします。これにより、ミドルウェアに大量のリダイレクトファイルをインポートすることを避けることができ、すべての受信リクエストが遅くなるのを防ぎます。 +存在する場合は、[Route Handler](/docs/app/building-your-application/routing/route-handlers) [API Routes](https://nextjs.org/docs/canary/pages/building-your-application/routing/api-routes)にリクエストを転送し、実際のファイルを確認してユーザーを適切な URL にリダイレクトします。これにより、Middleware に大容量のリダイレクトファイルをインポートする必要がなくなり、すべての受信リクエストが遅くなるのを防ぎます。 - + -```tsx title="middleware.ts" switcher +```ts title="middleware.ts" switcher import { NextResponse, NextRequest } from 'next/server' import { ScalableBloomFilter } from 'bloom-filters' import GeneratedBloomFilter from './redirects/bloom-filter.json' @@ -473,23 +473,23 @@ type RedirectEntry = { permanent: boolean } -// 生成されたJSONファイルからブルームフィルターを初期化する +// 生成された JSON ファイルからブルームフィルタを初期化 const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any) export async function middleware(request: NextRequest) { - // 受信リクエストのパスを取得する + // 受信リクエストのパスを取得 const pathname = request.nextUrl.pathname - // パスがブルームフィルターにあるかチェックする + // ブルームフィルタにパスがあるか確認 if (bloomFilter.has(pathname)) { - // パス名をRoute Handlerに転送する + // Route Handler にパスを転送 const api = new URL( `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`, request.nextUrl.origin ) try { - // Route Handlerからリダイレクトデータを取得する + // Route Handler からリダイレクトデータをフェッチ const redirectData = await fetch(api) if (redirectData.ok) { @@ -497,10 +497,10 @@ export async function middleware(request: NextRequest) { await redirectData.json() if (redirectEntry) { - // ステータスコードを決定する + // ステータスコードを決定 const statusCode = redirectEntry.permanent ? 308 : 307 - // 宛先にリダイレクトする + // 宛先にリダイレクト return NextResponse.redirect(redirectEntry.destination, statusCode) } } @@ -509,7 +509,7 @@ export async function middleware(request: NextRequest) { } } - // リダイレクトが見つからなかった場合、そのままリクエストを続行します + // リダイレクトが見つからなかった場合、リダイレクトなしでリクエストを続行 return NextResponse.next() } ``` @@ -522,33 +522,33 @@ import { NextResponse } from 'next/server' import { ScalableBloomFilter } from 'bloom-filters' import GeneratedBloomFilter from './redirects/bloom-filter.json' -// 生成されたJSONファイルからブルームフィルターを初期化する +// 生成された JSON ファイルからブルームフィルタを初期化 const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter) export async function middleware(request) { - // 受信リクエストのパスを取得する + // 受信リクエストのパスを取得 const pathname = request.nextUrl.pathname - // パスがブルームフィルターにあるかチェックする + // ブルームフィルタにパスがあるか確認 if (bloomFilter.has(pathname)) { - // パス名をRoute Handlerに転送する + // Route Handler にパスを転送 const api = new URL( `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`, request.nextUrl.origin ) try { - // Route Handlerからリダイレクトデータを取得する + // Route Handler からリダイレクトデータをフェッチ const redirectData = await fetch(api) if (redirectData.ok) { const redirectEntry = await redirectData.json() if (redirectEntry) { - // ステータスコードを決定する + // ステータスコードを決定 const statusCode = redirectEntry.permanent ? 308 : 307 - // 宛先にリダイレクトする + // 宛先にリダイレクト return NextResponse.redirect(redirectEntry.destination, statusCode) } } @@ -557,7 +557,7 @@ export async function middleware(request) { } } - // リダイレクトが見つからなかった場合、そのままリクエストを続行します + // リダイレクトが見つからなかった場合、リダイレクトなしでリクエストを続行 return NextResponse.next() } ``` @@ -567,12 +567,12 @@ export async function middleware(request) { -その後、Route Handlerでは: +そして、Route Handler の中で: - + -```tsx title="app/redirects/route.ts" switcher +```ts title="app/api/redirects/route.ts" switcher import { NextRequest, NextResponse } from 'next/server' import redirects from '@/app/redirects/redirects.json' @@ -584,15 +584,15 @@ type RedirectEntry = { export function GET(request: NextRequest) { const pathname = request.nextUrl.searchParams.get('pathname') if (!pathname) { - return new Response('不正なリクエスト', { status: 400 }) + return new Response('Bad Request', { status: 400 }) } - // redirects.jsonファイルからリダイレクトエントリを取得する + // redirects.json ファイルからリダイレクトエントリを取得 const redirect = (redirects as Record)[pathname] - // ブルームフィルターの誤検知に対応する + // ブルームフィルタの誤陽性を考慮 if (!redirect) { - return new Response('リダイレクトなし', { status: 400 }) + return new Response('No redirect', { status: 400 }) } // リダイレクトエントリを返す @@ -603,22 +603,22 @@ export function GET(request: NextRequest) { -```js title="app/redirects/route.js" switcher +```js title="app/api/redirects/route.js" switcher import { NextResponse } from 'next/server' import redirects from '@/app/redirects/redirects.json' export function GET(request) { const pathname = request.nextUrl.searchParams.get('pathname') if (!pathname) { - return new Response('不正なリクエスト', { status: 400 }) + return new Response('Bad Request', { status: 400 }) } - // redirects.jsonファイルからリダイレクトエントリを取得する + // redirects.json ファイルからリダイレクトエントリを取得 const redirect = redirects[pathname] - // ブルームフィルターの誤検知に対応する + // ブルームフィルタの誤陽性を考慮 if (!redirect) { - return new Response('リダイレクトなし', { status: 400 }) + return new Response('No redirect', { status: 400 }) } // リダイレクトエントリを返す @@ -633,12 +633,12 @@ export function GET(request) { -その後、API Routeでは: +そして、API Route の中で: - + -```tsx title="pages/api/redirects.ts" switcher +```ts title="pages/api/redirects.ts" switcher import type { NextApiRequest, NextApiResponse } from 'next' import redirects from '@/app/redirects/redirects.json' @@ -650,15 +650,15 @@ type RedirectEntry = { export default function handler(req: NextApiRequest, res: NextApiResponse) { const pathname = req.query.pathname if (!pathname) { - return res.status(400).json({ message: '不正なリクエスト' }) + return res.status(400).json({ message: 'Bad Request' }) } - // redirects.jsonファイルからリダイレクトエントリを取得する + // redirects.json ファイルからリダイレクトエントリを取得 const redirect = (redirects as Record)[pathname] - // ブルームフィルターの誤検知に対応する + // ブルームフィルタの誤陽性を考慮 if (!redirect) { - return res.status(400).json({ message: 'リダイレクトなし' }) + return res.status(400).json({ message: 'No redirect' }) } // リダイレクトエントリを返す @@ -675,15 +675,15 @@ import redirects from '@/app/redirects/redirects.json' export default function handler(req, res) { const pathname = req.query.pathname if (!pathname) { - return res.status(400).json({ message: '不正なリクエスト' }) + return res.status(400).json({ message: 'Bad Request' }) } - // redirects.jsonファイルからリダイレクトエントリを取得する + // redirects.json ファイルからリダイレクトエントリを取得 const redirect = redirects[pathname] - // ブルームフィルターの誤検知に対応する + // ブルームフィルタの誤陽性を考慮 if (!redirect) { - return res.status(400).json({ message: 'リダイレクトなし' }) + return res.status(400).json({ message: 'No redirect' }) } // リダイレクトエントリを返す @@ -696,7 +696,7 @@ export default function handler(req, res) { -> **参考情報**: +> **Good to know:** > -> - ブルームフィルターを生成するために、[`bloom-filters`](https://www.npmjs.com/package/bloom-filters)のようなライブラリを使用できます; -> - 悪意のあるリクエストを防止するために、Route Handlerに対して行われるリクエストを検証する必要があります; +> - ブルームフィルタを生成するには、[`bloom-filters`](https://www.npmjs.com/package/bloom-filters) のようなライブラリを使用できます。 +> - Route Handler に対するリクエストを検証して、悪意のあるリクエストを防ぐべきです。 diff --git a/docs/01-app/02-building-your-application/02-data-fetching/01-fetching.mdx b/docs/01-app/02-building-your-application/02-data-fetching/01-fetching.mdx index 357b81e..4d7c2d4 100644 --- a/docs/01-app/02-building-your-application/02-data-fetching/01-fetching.mdx +++ b/docs/01-app/02-building-your-application/02-data-fetching/01-fetching.mdx @@ -1,7 +1,7 @@ --- -title: 'データ取得とキャッシュ' -nav_title: 'データ取得とキャッシュ' -description: 'Next.jsでサーバーまたはクライアントでデータを取得するためのベストプラクティスを学びましょう。' +title: 'データの取得とキャッシング' +nav_title: 'データの取得とキャッシング' +description: 'Next.jsでサーバーまたはクライアントでデータを取得する際のベストプラクティスを学びましょう。' ---
@@ -13,9 +13,9 @@ description: 'Next.jsでサーバーまたはクライアントでデータを
-このガイドでは、Next.jsにおけるデータ取得とキャッシュの基本を実用的な例とベストプラクティスを示しながら説明します。 +このガイドでは、Next.jsでのデータ取得とキャッシングの基本を、実践的な例やベストプラクティスを交えて説明します。 -Next.jsにおけるデータ取得の最小限の例を以下に示します: +次に示すのは、Next.jsでのデータ取得の最小限の例です: @@ -54,9 +54,9 @@ export default async function Page() { -この例は、非同期のReact Server Componentで`fetch` APIを使用してサーバー側でデータを取得する基本的な方法を示しています。 +この例では、非同期のReact server componentで`fetch` APIを使用した基本的なサーバーサイドのデータ取得を示しています。 -## 参考 {#reference} +## 参考資料 {#reference} - [`fetch`](/docs/app/api-reference/functions/fetch) - React [`cache`](https://react.dev/reference/react/cache) @@ -64,9 +64,9 @@ export default async function Page() { ## 例 {#examples} -### サーバーで`fetch` APIを使用したデータ取得 {#fetching-data-on-the-server-with-the-fetch-api} +### `fetch` APIを使用したサーバーでのデータ取得 {#fetching-data-on-the-server-with-the-fetch-api} -このコンポーネントはブログ投稿のリストを取得して表示します。`fetch`からのレスポンスはデフォルトではキャッシュされません。 +このコンポーネントは、ブログ記事のリストを取得して表示します。`fetch`からのレスポンスはデフォルトではキャッシュされません。 @@ -105,19 +105,19 @@ export default async function Page() { -このルートの他の場所で[Dynamic APIs](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)を使用していない場合、`next build`中にこのページは静的ページとして事前レンダリングされます。その後、データは[Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)を使用して更新できます。 +このルートで他のどこにも [Dynamic APIs](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) を使用していない場合、ルートは`next build`中に静的ページとして事前レンダリングされます;データは、その後、[incremental static regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)を使用して更新できます; -ページの事前レンダリングを防ぐには、以下をファイルに追加します: +ページの事前レンダリングを防ぐには、次のコードをファイルに追加できます: ```js export const dynamic = 'force-dynamic' ``` -ただし、多くの場合、`cookies`、`headers`、またはページpropsからの`searchParams`を読み取る関数を使用します。これによりページは自動的に動的にレンダリングされます。この場合、`force-dynamic`を明示的に使用する必要はありません。 +ただし、通常`cookies`、`headers`、またはページpropsから来る`searchParams`を読み取る関数を使用する場合、この場合、ページは自動的に動的にレンダリングされるため、明示的に`force-dynamic`を使用する必要はありません。 -### ORMまたはデータベースを使用してサーバーでデータ取得 {#fetching-data-on-the-server-with-an-orm-or-database} +### ORMまたはデータベースを使用したサーバーでのデータ取得 {#fetching-data-on-the-server-with-an-orm-or-database} -このコンポーネントはブログ投稿のリストを取得して表示します。データベースからのレスポンスはデフォルトではキャッシュされていませんが、[追加の設定](#caching-data-with-an-orm-or-database)によってキャッシュすることができます。 +このコンポーネントは、ブログ記事のリストを取得して表示します。データベースからのレスポンスはデフォルトではキャッシュされませんが、[追加の設定](#caching-data-with-an-orm-or-database)でキャッシュできます。 @@ -158,21 +158,21 @@ export default async function Page() { -このルートの他の場所で[Dynamic APIs](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)を使用していない場合、`next build`中にこのページは静的ページとして事前レンダリングされます。その後、データは[Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)を使用して更新できます。 +このルートで他のDynamic APIsを使用していない場合、ルートは`next build`中に静的ページとして事前レンダリングされます;データは、その後、incremental static regenerationを使用して更新できます; -ページの事前レンダリングを防ぐには、以下をファイルに追加します: +ページの事前レンダリングを防ぐには、次のコードをファイルに追加できます: ```js export const dynamic = 'force-dynamic' ``` -ただし、多くの場合、`cookies`、`headers`、またはページpropsからの`searchParams`を読み取る関数を使用します。これによりページは自動的に動的にレンダリングされます。この場合、`force-dynamic`を明示的に使用する必要はありません。 +ただし、通常cookies、`headers`、またはページpropsから来る`searchParams`を読み取る関数を使用する場合、この場合、ページは自動的に動的にレンダリングされるため、明示的にforce-dynamicを使用する必要はありません。 -### クライアントでデータを取得する {#fetching-data-on-the-client} +### クライアントでのデータ取得 {#fetching-data-on-the-client} -最初にサーバーサイドでデータを取得することをお勧めします。 +最初にサーバーサイドでデータを取得することをお勧めします; -ただし、クライアントサイドのデータ取得が理にかなう場合もあります。その際には、`useEffect`で手動で`fetch`を呼び出す(推奨されません)か、クライアント取得のためにコミュニティの人気のあるReactライブラリ(例:[SWR](https://swr.vercel.app/)や[React Query](https://tanstack.com/query/latest))を利用することができます。 +しかし、クライアントサイドでのデータ取得が理にかなっているケースもあります;これらのシナリオでは、`useEffect`で手動で`fetch`を呼び出す(推奨されません)か、クライアントの取得にはコミュニティ内の人気のあるReactライブラリ([SWR](https://swr.vercel.app/)や[React Query](https://tanstack.com/query/latest)など)に頼ることができます; @@ -241,9 +241,9 @@ export function Posts() { -### ORMまたはデータベースによるデータキャッシュ {#caching-data-with-an-orm-or-database} +### ORMまたはデータベースでデータをキャッシュする {#caching-data-with-an-orm-or-database} -`unstable_cache` APIを使用してレスポンスをキャッシュし、`next build`実行時にページを事前レンダリングすることができます。 +`unstable_cache` APIを使用してレスポンスをキャッシュし、`next build`を実行するときにページを事前レンダリングできるようにします; @@ -304,22 +304,22 @@ export default async function Page() { -この例では、データベースクエリの結果を1時間(3600秒)キャッシュしています。また、キャッシュタグ`posts`を追加しており、後で[Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)でインバリデートすることができます。 +この例では、データベースクエリの結果を1時間(3600秒)キャッシュします;また、キャッシュタグ`posts`が追加され、incremental static regenerationで無効化することができます; ### 複数の関数でデータを再利用する {#reusing-data-across-multiple-functions} -Next.jsは、`generateMetadata`や`generateStaticParams`といったAPIを使用します。これらのAPIでは、`page`で取得したデータを使う必要があります。 +Next.jsは、`generateMetadata`や`generateStaticParams`のようなAPIを使用します;これらのAPIでは、`page`で取得された同じデータを使用する必要があります; -もし`fetch`を使用している場合、リクエストに`cache: 'force-cache'`を追加するとリクエストが[メモ化](/docs/app/building-your-application/caching#request-memoization)されます。これにより、同じオプションで同じURLを安全に呼び出すことができ、リクエストは1回のみ行われます。 +もし`fetch`を使用している場合、リクエストは`cache: 'force-cache'`を追加することで[memoized](/docs/app/building-your-application/caching#request-memoization)できます;これは、同じオプションで同じURLを安全に呼び出すことができ、1つのリクエストだけが行われることを意味します; -> **Good to know:** +> **Good to know:** > -> - 以前のバージョンのNext.jsでは、`fetch`を使用するとデフォルトの`cache`値は`force-cache`でした。バージョン15では、デフォルトが`cache: no-store`に変更されました。 +> - 以前のバージョンのNext.jsでは、`fetch`を使用するとデフォルトで`cache`の値が`force-cache`でした;これはバージョン15で変更され、デフォルトで`cache: no-store`になりました; -```tsx title="app/page.tsx" switcher +```tsx title="app/blog/[id]/page.tsx" switcher import { notFound } from 'next/navigation' interface Post { @@ -329,21 +329,21 @@ interface Post { } async function getPost(id: string) { - let res = await fetch(`https://api.vercel.app/blog/${id}`, { + const res = await fetch(`https://api.vercel.app/blog/${id}`, { cache: 'force-cache', }) - let post: Post = await res.json() + const post: Post = await res.json() if (!post) notFound() return post } export async function generateStaticParams() { - let posts = await fetch('https://api.vercel.app/blog', { + const posts = await fetch('https://api.vercel.app/blog', { cache: 'force-cache', }).then((res) => res.json()) return posts.map((post: Post) => ({ - id: post.id, + id: String(post.id), })) } @@ -352,7 +352,8 @@ export async function generateMetadata({ }: { params: Promise<{ id: string }> }) { - let post = await getPost(params.id) + const { id } = await params + const post = await getPost(id) return { title: post.title, @@ -364,7 +365,8 @@ export default async function Page({ }: { params: Promise<{ id: string }> }) { - let post = await getPost(params.id) + const { id } = await params + const post = await getPost(id) return (
@@ -378,28 +380,29 @@ export default async function Page({ -```jsx title="app/page.js" switcher +```jsx title="app/blog/[id]/page.js" switcher import { notFound } from 'next/navigation' async function getPost(id) { - let res = await fetch(`https://api.vercel.app/blog/${id}`) - let post = await res.json() + const res = await fetch(`https://api.vercel.app/blog/${id}`) + const post = await res.json() if (!post) notFound() return post } export async function generateStaticParams() { - let posts = await fetch('https://api.vercel.app/blog').then((res) => + const posts = await fetch('https://api.vercel.app/blog').then((res) => res.json() ) return posts.map((post) => ({ - id: post.id, + id: String(post.id), })) } export async function generateMetadata({ params }) { - let post = await getPost(params.id) + const { id } = await params + const post = await getPost(id) return { title: post.title, @@ -407,7 +410,8 @@ export async function generateMetadata({ params }) { } export default async function Page({ params }) { - let post = await getPost(params.id) + const { id } = await params + const post = await getPost(id) return (
@@ -421,11 +425,11 @@ export default async function Page({ params }) { -もし`fetch`を使用していない場合、ORMやデータベースを直接使用する代わりに、Reactの`cache`関数でデータ取得をラップできます。これにより重複が排除され、クエリは1回のみ行われます。 +`fetch`を使用していない場合、代わりにORMやデータベースを直接使用する場合は、Reactの`cache`関数でデータ取得をラップできます;これにより、重複が削除され、1回のクエリのみが行われます; ```jsx import { cache } from 'react' -import { db, posts, eq } from '@/lib/db' // Drizzle ORMでの例 +import { db, posts, eq } from '@/lib/db' // Drizzle ORMの例 import { notFound } from 'next/navigation' export const getPost = cache(async (id) => { @@ -440,30 +444,30 @@ export const getPost = cache(async (id) => { ### キャッシュされたデータの再検証 {#revalidating-cached-data} -[Incremental Static Regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)を使用したキャッシュされたデータの再検証について詳しく学びましょう。 +[incremental static regeneration](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)を使用して、キャッシュされたデータを再検証する方法を学びましょう; ## パターン {#patterns} -### 並列および逐次データ取得 {#parallel-and-sequential-data-fetching} +### 並列データ取得と順次データ取得 {#parallel-and-sequential-data-fetching} -コンポーネント内でデータを取得する際には、並列および逐次の2つのデータ取得パターンを意識する必要があります。 +コンポーネント内でデータを取得するときは、2つのデータ取得パターンに注意する必要があります:並列と順次です; 順次および並列データ取得 -- **逐次**: コンポーネントtree内でリクエストが互いに依存している。この結果、読み込み時間が長くなることがあります -- **並列**: route内のリクエストが積極的に開始され、データは同時に読み込まれます。これにより、データの読み込みにかかる全体の時間が短縮されます +- **順次**:コンポーネントtree内のリクエストが互いに依存している場合;これにより、読み込み時間が長くなる可能性があります; +- **並列**:route内のリクエストは積極的に開始され、同時にデータが読み込まれます;これにより、データを読み込むのにかかる総時間が短縮されます; -#### 逐次データ取得 {#sequential-data-fetching} +#### 順次データ取得 {#sequential-data-fetching} -ネストされたコンポーネントがあり、各コンポーネントが独自にデータを取得する場合、これらのデータリクエストが[メモ化](/docs/app/building-your-application/caching#request-memoization)されていない場合、データ取得は逐次的に行われます。 +ネストされたコンポーネントを持ちながら、それぞれのコンポーネントが独自のデータを取得する場合、それらのデータ要求が[memoized](/docs/app/building-your-application/caching#request-memoization)されていない場合、データ取得は順次で行われます; -このパターンが望ましい場合もあります。たとえば、`Playlists`コンポーネントは`Artist`コンポーネントがデータ取得を完了してからデータを取得し始めます。`Playlists`は`artistID` propに依存しているためです: +このパターンが求められるケースもあります;なぜなら、1つの取得が別の取得結果に依存しているからです;たとえば、`Playlists`コンポーネントは`Playlists`が`artistID` propに依存しているため、`Artist`コンポーネントがデータの取得を終えるまでデータの取得を始めません: @@ -474,7 +478,7 @@ export default async function Page({ }: { params: Promise<{ username: string }> }) { - // アーティスト情報の取得 + // アーティストの情報を取得 const artist = await getArtist(username) return ( @@ -508,7 +512,7 @@ async function Playlists({ artistID }: { artistID: string }) { ```jsx title="app/artist/[username]/page.js" switcher export default async function Page({ params: { username } }) { - // アーティスト情報の取得 + // アーティストの情報を取得 const artist = await getArtist(username) return ( @@ -540,19 +544,19 @@ async function Playlists({ artistID }) { -[`loading.js`](/docs/app/building-your-application/routing/loading-ui-and-streaming)(routeセグメント用)または[React ``](/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense)(ネストされたコンポーネント用)を使用して、即時の読み込み状態を表示することができます。 +[`loading.js`](/docs/app/building-your-application/routing/loading-ui-and-streaming)(routeセグメント用)や[React ``](/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense)(ネストされたコンポーネント用)を使用して、即時のローディング状態を表示し、Reactが結果をストリーミングする間に表示を続行できます; -これにより、データリクエストによってroute全体がブロックされるのを防ぎ、ユーザーは準備ができているページの部分と対話できるようになります。 +これによりデータ要求でroute全体がブロックされるのを防ぎ、準備ができているページの部分を操作できるようになります; #### 並列データ取得 {#parallel-data-fetching} -デフォルトで、レイアウトとページセグメントは並列にレンダリングされます。これにより、リクエストは並行して開始されます。 +デフォルトでは、レイアウトとページセグメントは並列にレンダリングされます;つまり、リクエストは並列で開始されます; -しかし、`async`/`await`の特性上、同じセグメントまたはコンポーネント内で待たれるリクエストはそれ以下のリクエストをブロックします。 +しかし、`async` / `await`の性質上、同じセグメントまたはコンポーネント内で待機しているリクエストは、その下にあるリクエストをブロックします; -データを並列に取得するには、データを使用するコンポーネントの外側でリクエストを定義して積極的に開始します。これにより、両方のリクエストが並行して開始され時間を節約しますが、両方のプロミスが解決されるまでユーザーはレンダリングされた結果を目にすることはありません。 +データを並列に取得するには、データを使用するコンポーネントの外でリクエストを積極的に開始することで、時間を節約します;これにより、両方のリクエストが並列に開始されます;ただし、ユーザーは両方のPromiseが解決されるまで表示結果を見られません; -下の例では、`getArtist`と`getAlbums`関数が`Page`コンポーネントの外側に定義され、コンポーネント内で`Promise.all`を使用して開始されます: +以下の例では、`getArtist`と`getAlbums`の関数が`Page`コンポーネント外で定義され、`Promise.all`を使用してコンポーネント内で開始されます: @@ -578,7 +582,7 @@ export default async function Page({ const artistData = getArtist(username) const albumsData = getAlbums(username) - // 両方のリクエストを並行して開始する + // 両方のリクエストを並列に開始 const [artist, albums] = await Promise.all([artistData, albumsData]) return ( @@ -610,7 +614,7 @@ export default async function Page({ params: { username } }) { const artistData = getArtist(username) const albumsData = getAlbums(username) - // 両方のリクエストを並行して開始する + // 両方のリクエストを並列に開始 const [artist, albums] = await Promise.all([artistData, albumsData]) return ( @@ -625,13 +629,13 @@ export default async function Page({ params: { username } }) { -さらに、[Suspense Boundary](/docs/app/building-your-application/routing/loading-ui-and-streaming)を追加することで、レンダリング作業を分割し可能な限り早く部分的な結果を表示することができます。 +さらに,[Suspense Boundary](/docs/app/building-your-application/routing/loading-ui-and-streaming)を追加してレンダリング作業を分割し、できるだけ早く部分的な結果を表示できます; -### データの事前ロード {#preloading-data} +### データのプリロード {#preloading-data} -ウォーターフォールを防ぐもう1つの方法は、ユーティリティ関数を作成し、ブロッキングリクエストの上で積極的に呼び出す*preload*パターンを使用することです。たとえば、`checkIsAvailable()`は``のレンダリングをブロックするので、`preload()`をその前に呼び出して``のデータ依存関係を積極的に開始できます。``がレンダリングされるとき、そのデータはすでに取得されています。 +ウォーターフォールを防ぐもう1つの方法は、ユーティリティ関数を作成してブロッキングリクエストの上で積極的に呼び出す`preload`パターンを使用することです;たとえば、`checkIsAvailable()` は``のレンダリングをブロックします;そのため`preload()`をその前に呼び出して`のデータ依存関係を積極的に開始します;``がレンダリングされる頃には、データはすでに取得されています; -なお、`preload`関数は`checkIsAvailable()`の実行をブロックしません。 +`preload`関数はが` checkIsAvailable()`の実行をブロックしないことに注意してください; @@ -640,7 +644,7 @@ export default async function Page({ params: { username } }) { import { getItem } from '@/utils/get-item' export const preload = (id: string) => { - // voidは指定された式を評価して未定義を返します。 + // voidは指定された式を評価し、undefinedを返します // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void void getItem(id) } @@ -657,7 +661,7 @@ export default async function Item({ id }: { id: string }) { import { getItem } from '@/utils/get-item' export const preload = (id) => { - // voidは指定された式を評価して未定義を返します。 + // voidは指定された式を評価し、undefinedを返します // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void void getItem(id) } @@ -709,11 +713,11 @@ export default async function Page({ params: { id } }) { -> **Good to know:** "preload"関数はAPIではなくパターンであるため、任意の名前を持つことができます。 +> **Good to know:** "preload"関数はAPIではなくパターンなので、名前は任意です; -#### Reactの`cache`と`server-only`を使用したPreloadパターン {#using-react-cache-and-server-only-with-the-preload-pattern} +#### React `cache`と`server-only`を使用するPreload Pattern {#using-react-cache-and-server-only-with-the-preload-pattern} -`cache`関数、preloadパターン、`server-only`パッケージを組み合わせて、アプリ全体で使用可能なデータ取得ユーティリティを作成することができます。 +React `cache`関数、`preload`パターン、および`server-only`パッケージを組み合わせて、アプリ全体で使用できるデータ取得ユーティリティを作成できます; @@ -750,17 +754,17 @@ export const getItem = cache(async (id) => { -このアプローチを使用すると、データを積極的に取得し、レスポンスをキャッシュし、このデータ取得が[サーバー上でのみ行われることを保証](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment)することができます。 +このアプローチを使用すると、データを積極的に取得し、レスポンスをキャッシュし、このデータ取得が[サーバーでのみ行われることを保証](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment)することができます; -`utils/get-item`エクスポートは、レイアウト、ページ、または他のコンポーネントによって使用され、アイテムのデータ取得のタイミングを制御することができます。 +`utils/get-item`のエクスポートは、レイアウト、ページ、または他のコンポーネントで使用され、アイテムのデータが取得されるタイミングを制御できます; -> **Good to know:** +> **Good to know:** > -> - サーバー側のデータ取得関数がクライアントで使用されないことを確認するために、[`server-only`パッケージ](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment)を使用することを推奨します。 +> - [`server-only` パッケージ](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment)を使用して、サーバーデータ取得関数が決してクライアントで使用されないようにすることをお勧めします; ### クライアントへの機密データの露出を防ぐ {#preventing-sensitive-data-from-being-exposed-to-the-client} -オブジェクトインスタンスや機密値全体がクライアントに渡されないようにするために、Reactの汚染API、[`taintObjectReference`](https://react.dev/reference/react/experimental_taintObjectReference)および[`taintUniqueValue`](https://react.dev/reference/react/experimental_taintUniqueValue)を使用することをお勧めします。 +Reactの汚染API、[`taintObjectReference`](https://react.dev/reference/react/experimental_taintObjectReference)と[`taintUniqueValue`](https://react.dev/reference/react/experimental_taintUniqueValue)を使用して、クライアントに渡すオブジェクト全体のインスタンスや機密値を防ぐことをお勧めします; アプリケーションで汚染を有効にするには、Next.js Configの`experimental.taint`オプションを`true`に設定します: @@ -787,11 +791,11 @@ import { export async function getUserData() { const data = await queryDataFromDB() experimental_taintObjectReference( - 'Do not pass the whole user object to the client', + 'クライアントに全体のユーザーオブジェクトを渡さないでください', data ) experimental_taintUniqueValue( - "Do not pass the user's address to the client", + 'クライアントにユーザーのアドレスを渡さないでください', data, data.address ) @@ -812,11 +816,11 @@ import { export async function getUserData() { const data = await queryDataFromDB() experimental_taintObjectReference( - 'Do not pass the whole user object to the client', + 'クライアントに全体のユーザーオブジェクトを渡さないでください', data ) experimental_taintUniqueValue( - "Do not pass the user's address to the client", + 'クライアントにユーザーのアドレスを渡さないでください', data, data.address ) @@ -837,8 +841,8 @@ export async function Page() { const userData = getUserData() return ( ) } @@ -854,8 +858,8 @@ export async function Page() { const userData = await getUserData() return ( ) } diff --git a/docs/01-app/02-building-your-application/02-data-fetching/04-incremental-static-regeneration.mdx b/docs/01-app/02-building-your-application/02-data-fetching/04-incremental-static-regeneration.mdx index 73684ad..de6dcf1 100644 --- a/docs/01-app/02-building-your-application/02-data-fetching/04-incremental-static-regeneration.mdx +++ b/docs/01-app/02-building-your-application/02-data-fetching/04-incremental-static-regeneration.mdx @@ -1,10 +1,10 @@ --- -title: 'Incremental Static Regeneration (ISR)' -description: 'Incremental Static Regenerationを使用して、実行時に静的ページを作成または更新する方法を学びます。' +title: 'インクリメンタル スタティック リジェネレーション (ISR)' +description: 'インクリメンタル スタティック リジェネレーションを使用して、ランタイムで静的ページを作成または更新する方法を学びます' ---
- + Examples - [Next.js Commerce](https://vercel.com/templates/next.js/nextjs-commerce) - [On-Demand ISR](https://on-demand-isr.vercel.app) @@ -12,14 +12,14 @@ description: 'Incremental Static Regenerationを使用して、実行時に静
-Incremental Static Regeneration (ISR)によって、以下のことが可能です: +インクリメンタル スタティック リジェネレーション (ISR) により、以下を行うことができます: -- サイト全体をリビルドすることなく静的コンテンツを更新する -- プリレンダリングされた静的ページをほとんどのリクエストに提供することで、サーバー負荷を軽減する -- ページに正しい`cache-control`ヘッダーを自動的に加えるようにする -- `next build`が長時間かかることなく、膨大なコンテンツページを処理する +- サイト全体を再構築せずに静的コンテンツを更新する +- プリレンダーされた静的ページをほとんどのリクエストに対して提供することでサーバー負荷を軽減する +- 適切な `cache-control` ヘッダーがページに自動的に追加されるようにする +- `next build` の時間を長くすることなく、大量のコンテンツページを処理する -これが最小の例です: +以下は最小の例です: @@ -33,14 +33,14 @@ interface Post { content: string } -// リクエストが来た際、Next.jsはキャッシュを無効化し、 -// 最大60秒ごとに一度だけ更新します。 +// Next.js はキャッシュを無効化します、 +// リクエストが届いた場合、最大で60秒ごとに。 export const revalidate = 60 -// ビルド時には`generateStaticParams`によるパラメータのみをプリレンダリングします。 -// ランダムなリクエストがまだ生成されていないパスの場合、 -// Next.jsはそのページを要求時にサーバーレンダリングします。 -export const dynamicParams = true // またはfalseにして未確認パスで404を表示 +// ビルド時に `generateStaticParams` からの params のみプリレンダーします。 +// 生成されていないパスに対するリクエストが届いた場合、 +// Next.js はページをオンデマンドでサーバーレンダリングします。 +export const dynamicParams = true // または false、不明なパスでは404にする export async function generateStaticParams() { const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) => @@ -51,10 +51,15 @@ export async function generateStaticParams() { })) } -export default async function Page({ params }: { params: { id: string } }) { - const post: Post = await fetch( - `https://api.vercel.app/blog/${params.id}` - ).then((res) => res.json()) +export default async function Page({ + params, +}: { + params: Promise<{ id: string }> +}) { + const id = (await params).id + const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then( + (res) => res.json() + ) return (

{post.title}

@@ -68,14 +73,14 @@ export default async function Page({ params }: { params: { id: string } }) { ```jsx title="app/blog/[id]/page.js" switcher -// リクエストが来た際、Next.jsはキャッシュを無効化し、 -// 最大60秒ごとに一度だけ更新します。 +// Next.js はキャッシュを無効化します、 +// リクエストが届いた場合、最大で60秒ごとに。 export const revalidate = 60 -// ビルド時には`generateStaticParams`によるパラメータのみをプリレンダリングします。 -// ランダムなリクエストがまだ生成されていないパスの場合、 -// Next.jsはそのページを要求時にサーバーレンダリングします。 -export const dynamicParams = true // またはfalseにして未確認パスで404を表示 +// ビルド時に `generateStaticParams` からの params のみプリレンダーします。 +// 生成されていないパスに対するリクエストが届いた場合、 +// Next.js はページをオンデマンドでサーバーレンダリングします。 +export const dynamicParams = true // または false、不明なパスでは404にする export async function generateStaticParams() { const posts = await fetch('https://api.vercel.app/blog').then((res) => @@ -87,8 +92,9 @@ export async function generateStaticParams() { } export default async function Page({ params }) { - const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then( - (res) => res.json() + const { id } = await params + const post = await fetch(`https://api.vercel.app/blog/${id}`).then((res) => + res.json() ) return (
@@ -130,9 +136,8 @@ export const getStaticPaths: GetStaticPaths = async () => { params: { id: String(post.id) }, })) - // ビルド時にのみこれらのパスをプリレンダリングします。 - // { fallback: 'blocking' }はパスが存在しない場合に - // サーバーがページを要求時にレンダリングします。 + // ビルド時にこれらのパスのみをプリレンダーします。 + // { fallback: 'blocking' }は、パスが存在しない場合にページをオンデマンドでサーバーレンダリングします。 return { paths, fallback: false } } @@ -147,8 +152,8 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はキャッシュを無効化します、 + // リクエストが届いた場合、最大で60秒ごとに。 revalidate: 60, } } @@ -175,8 +180,8 @@ export async function getStaticPaths() { params: { id: post.id }, })) - // ビルド時にのみこれらのパスをプリレンダリングします。 - // { fallback: false }は他のルートが404であるべきことを意味します。 + // ビルド時にこれらのパスのみをプリレンダーします。 + // { fallback: false }は他のルートが404になることを意味します。 return { paths, fallback: false } } @@ -187,8 +192,8 @@ export async function getStaticProps({ params }) { return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はキャッシュを無効化します、 + // リクエストが届いた場合、最大で60秒ごとに。 revalidate: 60, } } @@ -208,20 +213,20 @@ export default function Page({ post }) { -この例の動作は次のとおりです: +この例の仕組みは次のとおりです: -1. `next build`の際、既知のブログ投稿がすべて生成されます(この例では25件あります) -2. これらのページへのすべてのリクエスト(例:`/blog/1`)はキャッシュされ、瞬時に応答します -3. 60秒が経過した後も、次のリクエストはキャッシュされた(古い)ページを表示します +1. `next build` の間に、すべての既知のブログ投稿が生成されます(この例では25) +2. これらのページへのすべてのリクエスト(例:`/blog/1`)はキャッシュされており、即時に返されます +3. 60秒経過後、次のリクエストでは引き続きキャッシュされたページ(古いページ)が表示されます 4. キャッシュが無効化され、新しいバージョンのページがバックグラウンドで生成され始めます -5. 正常に生成されると、Next.jsは更新されたページを表示し、キャッシュします -6. `/blog/26`へのリクエストがあった場合、Next.jsはこのページを要求時に生成してキャッシュします +5. 成功裏に生成されると、Next.js は更新されたページを表示しキャッシュします +6. `/blog/26` がリクエストされた場合、Next.js はこのページをオンデマンドで生成しキャッシュします -## リファレンス {#reference} +## 参考文献 {#reference} -### Route segment config {#route-segment-config} +### ルートセグメント設定 {#route-segment-config} - [`revalidate`](/docs/app/api-reference/file-conventions/route-segment-config#revalidate) - [`dynamicParams`](/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams) @@ -246,9 +251,9 @@ export default function Page({ post }) { -### 時間に基づく再検証 {#time-based-revalidation} +### 時間ベースのリバリデーション {#time-based-revalidation} -これは`/blog`にブログ投稿のリストを表示します。1時間後、このページのキャッシュは次の訪問で無効化されます。そして、バックグラウンドで新しいバージョンのページが最新のブログ投稿を伴って生成されます。 +これは、`/blog` 上でブログ投稿のリストを取得し表示します。1時間後、このページのキャッシュは次回のページ訪問時に無効化されます。すると、バックグラウンドで新しいバージョンのページが生成され、最新のブログ投稿が含まれます。 @@ -260,7 +265,7 @@ interface Post { content: string } -export const revalidate = 3600 // 毎時間無効化 +export const revalidate = 3600 // 毎時無効化 export default async function Page() { const data = await fetch('https://api.vercel.app/blog') @@ -282,7 +287,7 @@ export default async function Page() { ```jsx title="app/blog/page.js" switcher -export const revalidate = 3600 // 毎時間無効化 +export const revalidate = 3600 // 毎時無効化 export default async function Page() { const data = await fetch('https://api.vercel.app/blog') @@ -303,13 +308,13 @@ export default async function Page() { -高い再検証時間を設定することをお勧めします。例えば、1秒ではなく1時間にします。より正確な制御が必要な場合は、オンデマンドの再検証を検討してください。リアルタイムデータが必要な場合は、[dynamic rendering](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)に切り替えることを検討してください。 +長いリバリデーション時間を設定することをお勧めします。たとえば、1秒ではなく1時間です。より精度が必要な場合は、オンデマンド リバリデーションの使用を検討してください。リアルタイムデータが必要な場合は、[動的レンダリング](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)への切り替えを検討してください。 -### `revalidatePath`を使ったオンデマンドの再検証 {#on-demand-revalidation-with-revalidatepath} +### `revalidatePath` を使ったオンデマンドリバリデーション {#on-demand-revalidation-with-revalidatepath} -再検証のより正確な方法として、`revalidatePath`関数を使用してオンデマンドでページを無効化します。 +より精密なリバリデーション方法として、`revalidatePath` 関数を使ってオンデマンドでページを無効化します。 -例えば、新しい投稿を追加した後にこのServer Actionが呼び出されるとします。Server Componentでデータを取得する方法に関係なく、either `fetch`やデータベースへの接続を使用して、これはルート全体のキャッシュをクリアし、Server Componentが最新のデータを取得できるようにします。 +たとえば、このServer Actionは新しい投稿を追加した後に呼び出されます。データを取得する方法に関わらず、`fetch`を使用するかデータベースに接続するかにかかわらず、これによりルート全体のキャッシュがクリアされ、Server Componentが新しいデータを取得できるようになります。 @@ -320,7 +325,7 @@ export default async function Page() { import { revalidatePath } from 'next/cache' export async function createPost() { - // キャッシュ内の/postsルートを無効化 + // キャッシュ内の /posts ルートを無効化します revalidatePath('/posts') } ``` @@ -334,7 +339,7 @@ export async function createPost() { import { revalidatePath } from 'next/cache' export async function createPost() { - // キャッシュ内の/postsルートを無効化 + // キャッシュ内の /posts ルートを無効化します revalidatePath('/posts') } ``` @@ -342,11 +347,11 @@ export async function createPost() { -[デモを見る](https://on-demand-isr.vercel.app)と[ソースコードを探る](https://github.com/vercel/on-demand-isr). +[デモを表示](https://on-demand-isr.vercel.app)し、[ソースコードを探索](https://github.com/vercel/on-demand-isr))。 -### `revalidateTag`を使ったオンデマンドの再検証 {#on-demand-revalidation-with-revalidatetag} +### `revalidateTag` を使ったオンデマンドリバリデーション {#on-demand-revalidation-with-revalidatetag} -ほとんどのユースケースでは、パス全体を再検証することをお勧めします。より細かい制御が必要な場合は、`revalidateTag`関数を使用できます。例えば、個別の`fetch`呼び出しにタグを付けることができます: +ほとんどのユースケースでは、パス全体をリバリデーションすることをお勧めします。より詳細な制御が必要な場合は、`revalidateTag` 関数を使えます。たとえば、個々の`fetch`コールにタグを付けることができます: @@ -377,7 +382,7 @@ export default async function Page() { -ORMを使用している場合やデータベースに接続している場合は、`unstable_cache`を使用できます: +ORMを使用した場合やデータベースに接続した場合、`unstable_cache` を使えます: @@ -424,7 +429,7 @@ export default async function Page() { -その後、[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)や[Route Handler](/docs/app/building-your-application/routing/route-handlers)で`revalidateTag`を使用できます: +その後、[Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)または[Route Handler](/docs/app/building-your-application/routing/route-handlers)で `revalidateTag` を使用できます: @@ -435,8 +440,7 @@ export default async function Page() { import { revalidateTag } from 'next/cache' export async function createPost() { - // キャッシュ内の'tags'でタグ付けされた - // すべてのデータを無効化 + // キャッシュ内の 'posts' タグ付きすべてのデータを無効化します revalidateTag('posts') } ``` @@ -450,8 +454,7 @@ export async function createPost() { import { revalidateTag } from 'next/cache' export async function createPost() { - // キャッシュ内の'tags'でタグ付けされた - // すべてのデータを無効化 + // キャッシュ内の 'posts' タグ付きすべてのデータを無効化します revalidateTag('posts') } ``` @@ -463,11 +466,11 @@ export async function createPost() { -### `res.revalidate()`を用いたオンデマンド検証 {#on-demand-validation-with-res-revalidate} +### `res.revalidate()` を使ったオンデマンドの検証 {#on-demand-validation-with-res-revalidate} -再検証のより正確な方法として、`res.revalidate`を使用してAPIルーターからオンデマンドで新しいページを生成します。 +より精密なリバリデーション方法として、`res.revalidate` を使用して API ルーターからオンデマンドで新しいページを生成します。 -例えば、`/api/revalidate?secret=`で指定されたブログポストを再検証できるこのAPIルートがあります。Next.jsアプリにのみ知られている秘密のトークンを作成します。この秘密は、再検証APIルートへの不正アクセスを防ぐために使用されます。 +たとえば、この API ルートは `/api/revalidate?secret=` で呼び出され、指定されたブログ投稿をリバリデーションします。Next.js アプリでのみ知られている秘密トークンを作成します。この秘密はリバリデーション API ルートへの不正アクセスを防ぐために使用されます。 @@ -479,19 +482,19 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - // 秘密確認のために正当な要求かどうか確認します + // このリクエストが有効であることを確認するための秘密を確認します if (req.query.secret !== process.env.MY_SECRET_TOKEN) { return res.status(401).json({ message: 'Invalid token' }) } try { - // 実際のパスであり、書き換えられていないパスであるべきです - // 例: "/posts/[id]"なら"/posts/1"であるべきです + // これは書き換えられたパスではなく、実際のパスである必要があります + // 例:"/posts/[id]" この場合は "/posts/1" await res.revalidate('/posts/1') return res.json({ revalidated: true }) } catch (err) { - // エラーが発生した場合、Next.jsは - // 最後に正常に生成されたページを表示し続けます + // エラーが発生した場合、Next.jsは最後に成功したページを + // 引き続き表示します return res.status(500).send('Error revalidating') } } @@ -502,19 +505,19 @@ export default async function handler( ```js title="pages/api/revalidate.js" switcher export default async function handler(req, res) { - // 秘密確認のために正当な要求かどうか確認します + // このリクエストが有効であることを確認するための秘密を確認します if (req.query.secret !== process.env.MY_SECRET_TOKEN) { return res.status(401).json({ message: 'Invalid token' }) } try { - // 実際のパスであり、書き換えられていないパスであるべきです - // 例: "/posts/[id]"なら"/posts/1"であるべきです + // これは書き換えられたパスではなく、実際のパスである必要があります + // 例:"/posts/[id]" この場合は "/posts/1" await res.revalidate('/posts/1') return res.json({ revalidated: true }) } catch (err) { - // エラーが発生した場合、Next.jsは - // 最後に正常に生成されたページを表示し続けます + // エラーが発生した場合、Next.jsは最後に成功したページを + // 引き続き表示します return res.status(500).send('Error revalidating') } } @@ -523,21 +526,21 @@ export default async function handler(req, res) { -オンデマンド再検証を使用している場合、`getStaticProps`内で`revalidate`時間を指定する必要はありません。Next.jsはデフォルト値の`false`(再検証なし)を使い、`res.revalidate()`が呼び出されたときにのみページを再検証します。 +オンデマンドリバリデーションを使用している場合、`getStaticProps` 内で `revalidate` 時間を指定する必要はありません。Next.js はデフォルト値として `false`(リバリデーションなし)を使用し、`res.revalidate()` が呼び出されたときにのみオンデマンドでページをリバリデーションします。 -### キャッシュされていない例外を処理する {#handling-uncaught-exceptions} +### 未捕捉例外の処理 {#handling-uncaught-exceptions} -データを再検証しようとするときにエラーが発生した場合、最後に正常に生成されたデータがキャッシュから提供され続けます。次のリクエスト時に、Next.jsはデータの再検証を試みます。[エラー処理についての詳細を学ぶ](/docs/app/building-your-application/routing/error-handling). +データのリバリデーションを試みる際にエラーが発生した場合は、最後に正常に生成されたデータがキャッシュから提供され続けます。次回のリクエスト時にNext.jsは再試行してデータのリバリデーションを行います。[エラー処理について詳しく学ぶ](/docs/app/building-your-application/routing/error-handling)。 -バックグラウンド再生成を処理する際に`getStaticProps`内でエラーが発生した場合、またはエラーを手動で投げた場合、最後に正常に生成されたページが表示され続けます。次のリクエスト時には、Next.jsは`getStaticProps`を再度呼び出します。 +バックグラウンドリジェネレーションを処理しているときに `getStaticProps` 内でエラーが発生する場合、または手動でエラーをスローする場合、最後に生成されたページが引き続き表示されます。次回のリクエスト時に Next.js は `getStaticProps` の再試行を行います。 @@ -560,22 +563,22 @@ export const getStaticProps: GetStaticProps = async ({ }: { params: { id: string } }) => { - // このリクエストがキャッチされないエラーを発生させた場合、Next.jsは - // 現在表示されているページを無効化せず、 - // 次のリクエストで再度getStaticPropsを試みます。 + // このリクエストが予期しないエラーをスローした場合、Next.js は + // 現在表示中のページを無効にせず、 + // 次回のリクエスト時に getStaticProps を再試行します。 const res = await fetch(`https://api.vercel.app/blog/${params.id}`) const post: Post = await res.json() if (!res.ok) { - // サーバーエラーがある場合、キャッシュの - // 更新を避けるためにエラーを投げたほうがよいかもしれません。 + // サーバーエラーがある場合、キャッシュ更新まで + // 次の成功リクエストまで、エラーをスローしたいかもしれません。 throw new Error(`Failed to fetch posts, received status ${res.status}`) } return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はキャッシュを無効化します、 + // リクエストが届いた場合、最大で60秒ごとに。 revalidate: 60, } } @@ -586,22 +589,22 @@ export const getStaticProps: GetStaticProps = async ({ ```jsx title="pages/blog/[id].jsx" switcher export async function getStaticProps({ params }) { - // このリクエストがキャッチされないエラーを発生させた場合、Next.jsは - // 現在表示されているページを無効化せず、 - // 次のリクエストで再度getStaticPropsを試みます。 + // このリクエストが予期しないエラーをスローした場合、Next.js は + // 現在表示中のページを無効にせず、 + // 次回のリクエスト時に getStaticProps を再試行します。 const res = await fetch(`https://api.vercel.app/blog/${params.id}`) const post = await res.json() if (!res.ok) { - // サーバーエラーがある場合、キャッシュの - // 更新を避けるためにエラーを投げたほうがよいかもしれません。 + // サーバーエラーがある場合、キャッシュ更新まで + // 次の成功リクエストまで、エラーをスローしたいかもしれません。 throw new Error(`Failed to fetch posts, received status ${res.status}`) } return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はキャッシュを無効化します、 + // リクエストが届いた場合、最大で60秒ごとに。 revalidate: 60, } } @@ -612,19 +615,19 @@ export async function getStaticProps({ params }) { -### キャッシュの保存場所をカスタマイズする {#customizing-the-cache-location} +### キャッシュ場所のカスタマイズ {#customizing-the-cache-location} -(Incremental Static Regenerationを使用して)ページをキャッシュし再検証するには、同じ共有キャッシュが使用されます。 [Vercelへデプロイする](https://vercel.com/docs/incremental-static-regeneration?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)場合、ISRキャッシュは自動的に耐久性のあるストレージに永続化されます。 +ページのキャッシュとリバリデーション(インクリメンタル スタティック リジェネレーションを使用)では、同じ共有キャッシュが使用されます。 [Vercel へのデプロイ](https://vercel.com/docs/incremental-static-regeneration?utm_source=next-site&utm_medium=docs&utm_campaign=next-website)時に、ISR キャッシュは自動的に永続的なストレージに保存されます。 -自己ホスティングする場合、ISRキャッシュはNext.jsサーバーでファイルシステム(ディスク上)に保存されます。これは、PagesやApp Routerを使用した自己ホスティング時に自動的に機能します。 +セルフホスティングの場合、ISR キャッシュは Next.js サーバーのファイルシステム(ディスク)に保存されます。これは、ページおよびApp Router の両方を使用してセルフホスティングする場合に自動的に機能します。 -キャッシュされたページとデータを耐久性のあるストレージに永続化したり、Next.jsアプリケーションの複数のコンテナやインスタンス間でキャッシュを共有したい場合、Next.jsキャッシュロケーションを設定できます。[詳細を学ぶ](/docs/app/building-your-application/deploying#caching-and-isr). +キャッシュされたページとデータを永続ストレージに保存するか、Next.js アプリケーションの複数のコンテナまたはインスタンス間でキャッシュを共有したい場合は、Next.js のキャッシュ場所を設定できます。[詳しく学ぶ](/docs/app/building-your-application/deploying#caching-and-isr)。 ## トラブルシューティング {#troubleshooting} -### ローカル開発時にキャッシュデータをデバッグする {#debugging-cached-data-in-local-development} +### ローカル開発でのキャッシュデータのデバッグ {#debugging-cached-data-in-local-development} -`fetch` APIを使用している場合、どのようなリクエストがキャッシュされているか非キャッシュされているかを理解するために追加のロギングを加えることができます。[`logging` オプションについて詳しく学ぶ](/docs/app/api-reference/config/next-config-js/logging). +`fetch` API を使用している場合、リクエストがキャッシュされているかキャッシュされていないかを理解するために追加のロギングを追加できます。[`logging` オプションについて詳しく学ぶ](/docs/app/api-reference/config/next-config-js/logging)。 ```jsx title="next.config.js" module.exports = { @@ -636,44 +639,44 @@ module.exports = { } ``` -### 正しい本番動作を確認する {#verifying-correct-production-behavior} +### 正しい本番動作の確認 {#verifying-correct-production-behavior} -本番環境でページが正しくキャッシュされ再検証されることを確認するには、`next build`を実行してから`next start`で本番のNext.jsサーバーをローカルで実行することでテストできます。 +本番でページがキャッシュされてリバリデートされているかを確認するために、`next build` を実行してから `next start` を実行して、プロダクション Next.js サーバーをローカルでテストできます。 -これにより、本番環境で動作するようにISRの動作をテストできます。さらにデバッグするには、以下の環境変数を`.env`ファイルに追加してください: +これにより、プロダクション環境での ISR の動作をテストすることができます。さらなるデバッグのために、次の環境変数を `.env` ファイルに追加します: ```bash title=".env" NEXT_PRIVATE_DEBUG_CACHE=1 ``` -これにより、Next.jsサーバーのコンソールログでISRキャッシュヒットとミスが表示されます。どのページが`next build`中に生成されるか、およびオンデマンドでパスがアクセスされる際にページがどのように更新されるかを出力を調査できます。 +これにより、Next.js サーバーコンソールログに ISR キャッシュヒットとミスが表示されます。`next build` 中に生成されたページ、およびパスがオンデマンドでアクセスされたときにページがどのように更新されるかを確認するために出力を検査できます。 -## 制約 {#caveats} +## 注意点 {#caveats} -- ISRは、Node.jsランタイム(デフォルト)の使用時のみサポートされています。 -- ISRは、 [Static Exportを作成する](/docs/app/building-your-application/deploying/static-exports)際にはサポートされていません。 -- 静的にレンダリングされたルートに複数の`fetch`リクエストがあり、それぞれ異なる`revalidate`頻度を持つ場合、最低の時間がISRに使われます。ただし、これらの再検証頻度は[Data Cache](/docs/app/building-your-application/caching#data-cache)によって引き続き尊重されます。 -- ルートで使用されている`fetch`リクエストのいずれかが`revalidate`時間を`0`に設定している場合、または明示的に`no-store`を使用している場合、そのルートは [dynamic renderingとしてレンダリングされます](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)。 -- オンデマンドISRリクエストではMiddlewareが実行されないため、Middleware内の任意のパス書き換えやロジックは適用されません。正確なパスを再検証していることを確認してください。例えば、書き換えられた`/post-1`ではなく、`/post/1`です。 +- ISR は Node.js ランタイムを使用する場合にのみサポートされています(デフォルト)。 +- ISR は[Static Export](/docs/app/building-your-application/deploying/static-exports)を作成する際にはサポートされていません。 +- 静的にレンダリングされたルートに複数の `fetch` リクエストがあり、それぞれが異なる `revalidate` 周期を持っている場合、ISR には最短時間が使用されます。 しかし、これらのリバリデート頻度は[データキャッシュ](/docs/app/building-your-application/caching#data-cache) によって依然として尊重されます。 +- ルートで使用されている `fetch` リクエストのどれかが `revalidate` 時間として `0` または明示的な `no-store` を持っている場合、そのルートは[動的にレンダリングされる](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) ことになります。 +- ミドルウェアはオンデマンドISRリクエストに対して実行されないため、ミドルウェア内のパスリライトやロジックは適用されません。正確なパスをリバリデートしていることを確認してください。たとえば、書き換えられた `/post-1` ではなく、`/post/1` のようにします。 -- ISRは、Node.jsランタイム(デフォルト)の使用時のみサポートされています。 -- ISRは、 [Static Exportを作成する](/docs/app/building-your-application/deploying/static-exports)際にはサポートされていません。 -- オンデマンドISRリクエストではMiddlewareが実行されないため、Middleware内の任意のパス書き換えやロジックは適用されません。正確なパスを再検証していることを確認してください。例えば、書き換えられた`/post-1`ではなく、`/post/1`です。 +- ISR は Node.js ランタイムを使用する場合にのみサポートされています(デフォルト)。 +- ISR は[Static Export](/docs/app/building-your-application/deploying/static-exports)を作成する際にはサポートされていません。 +- ミドルウェアはオンデマンドISRリクエストに対して実行されないため、ミドルウェア内のパスリライトやロジックは適用されません。正確なパスをリバリデートしていることを確認してください。たとえば、書き換えられた `/post-1` ではなく、`/post/1` のようにします。 ## バージョン履歴 {#version-history} -| バージョン | 変更内容 | -| ---------- | ----------------------------------------------------------------------------------------------------- | -| `v14.1.0` | カスタム`cacheHandler`が安定版になりました。 | -| `v13.0.0` | App Routerが導入されました。 | -| `v12.2.0` | Pages Router:オンデマンドISRが安定しています | -| `v12.0.0` | Pages Router:[Bot-aware ISR fallback](https://nextjs.org/blog/next-12#bot-aware-isr-fallback) 追加。 | -| `v9.5.0` | Pages Router:[安定したISRが導入されました](https://nextjs.org/blog/next-9-5)。 | +| バージョン | 変更点 | +| ---------- | ----------------------------------------------------------------------------------------------------------------- | +| `v14.1.0` | カスタム `cacheHandler` が安定版になりました。 | +| `v13.0.0` | App Router が導入されました。 | +| `v12.2.0` | Pages Router:オンデマンドISRが安定版になりました | +| `v12.0.0` | Pages Router:[Bot-aware ISR fallback](https://nextjs.org/blog/next-12#bot-aware-isr-fallback) が追加されました。 | +| `v9.5.0` | Pages Router:[安定版 ISR が導入されました](https://nextjs.org/blog/next-9-5) | diff --git a/docs/01-app/02-building-your-application/03-rendering/01-server-components.mdx b/docs/01-app/02-building-your-application/03-rendering/01-server-components.mdx index 1a376b7..2d10ef9 100644 --- a/docs/01-app/02-building-your-application/03-rendering/01-server-components.mdx +++ b/docs/01-app/02-building-your-application/03-rendering/01-server-components.mdx @@ -1,103 +1,103 @@ --- title: 'Server Components' -description: 'アプリケーションの一部をサーバーでレンダリングするために、React Server Componentsを使用する方法を学びます。' +description: 'React Server Components を使用して、アプリケーションの一部をサーバーでレンダリングする方法を学びます。' related: - description: 'Next.jsがデータと静的レンダリングの結果をどのようにキャッシュするかを学びます。' + description: 'Next.js がデータと静的レンダリングの結果をどのようにキャッシュするかを学びます。' links: - app/building-your-application/caching --- -React Server Componentsを使用すると、UIをサーバーでレンダリングでき、オプションでキャッシュすることができます。Next.jsでは、ストリーミングと部分レンダリングを可能にするために、レンダリング作業がルートセグメントによってさらに分割されます。サーバーレンダリング戦略には以下の3つがあります: +React Server Components を使用すると、サーバー側でレンダリングされる UI を記述できます。また、サーバーでキャッシュすることも選択できます。Next.js では、ストリーミングと部分的なレンダリングを可能にするために、レンダリング作業がルートセグメントによってさらに分割され、3つの異なるサーバーレンダリング戦略があります: - [静的レンダリング](#static-rendering-default) - [動的レンダリング](#dynamic-rendering) - [ストリーミング](#streaming) -このページでは、Server Components がどのように機能するか、いつ使用するか、異なるサーバーレンダリング戦略について説明します。 +このページでは、Server Component の動作方法、使用するケース、および異なるサーバーレンダリング戦略について説明します。 ## サーバーレンダリングの利点 {#benefits-of-server-rendering} -サーバーでレンダリング作業を行うことには、次のような利点があります: +サーバー上でレンダリング作業を行うことには、いくつかの利点があります。以下の項目が含まれます: -- **データ取得**:Server Components を使用すると、データ取得をサーバーに移動できます。これにより、レンダリングに必要なデータを取得する時間を短縮し、クライアントが行うリクエストの数を減らすことでパフォーマンスを向上させることができます。 -- **セキュリティ**:Server Components を使用すると、トークンやAPIキーなどの機密データとロジックをクライアントに公開せずにサーバーに保持できます。 -- **キャッシング**:サーバーでレンダリングされた結果はキャッシュされ、後続のリクエストやユーザー間で再利用できます。これにより、各リクエストで行われるレンダリングおよびデータ取得の量を削減し、パフォーマンスを向上させ、コストを削減できます。 -- **パフォーマンス**:Server Components は、ベースラインからのパフォーマンスを最適化するための追加のツールを提供します。たとえば、完全に Client Components で構成されたアプリから始めて、UIの非インタラクティブな部分を Server Components に移行することで、クライアント側のJavaScriptの量を削減できます。これは、インターネット速度が遅いか、デバイスがあまり強力でないユーザーにとって有益です。ブラウザがダウンロード、解析、および実行するクライアント側のJavaScriptが少なくて済みます。 -- **初期ページロードと[最初のコンテンツフルペイント (FCP)](https://web.dev/fcp/)**:サーバーでHTMLを生成することで、クライアントがページをレンダリングするために必要なJavaScriptをダウンロード、解析、および実行するのを待たずに、ユーザーがページを直ちに表示できるようにします。 -- **検索エンジン最適化とソーシャルネットワーク共有可能性**:レンダリングされたHTMLは、検索エンジンボットによってページをインデックス化するため、またソーシャルネットワークボットがページのソーシャルカードプレビューを生成するために使用されます。 -- **ストリーミング**:Server Components は、レンダリング作業をチャンクに分割し、準備が整うとすぐにクライアントにストリーム配信できます。これにより、ページ全体がサーバーでレンダリングされるのを待たずに、ページの一部を早期に表示できます。 +- **データフェッチング**:Server Component を使用すると、データフェッチングをサーバーに移動できます。これにより、レンダリングに必要なデータの取得時間が短縮され、クライアントが行うリクエストの数も減少します。 +- **セキュリティ**:Server Component を使用すると、トークンや API キーなどの機密データとロジックをサーバー上に保持できます。これにより、クライアントにさらすリスクを回避できます。 +- **キャッシュ**:サーバーでレンダリングすることにより、その結果をキャッシュして、後続のリクエストおよびユーザー間で再利用することができます。これにより、各リクエストで行うレンダリングやデータフェッチングの量を減らして、パフォーマンスを向上させ、コストを削減できます。 +- **パフォーマンス**:Server Component は、基本パフォーマンスを最適化するための追加ツールを提供します。たとえば、完全に Client Component で構成されたアプリから始めた場合、UI の非対話部分を Server Component に移動することで、必要なクライアントサイド JavaScript の量を削減できます。これにより、遅いインターネットや性能の低いデバイスを持つユーザーにもメリットがあります。ブラウザがダウンロード、解析、実行するクライアントサイド JavaScript が少なるためです。 +- **初期ページロードと[ファースト コンテンツフル ペイント(FCP)](https://web.dev/fcp/)**:サーバー上で HTML を生成することで、クライアントが JavaScript のダウンロード、解析、ページのレンダリングに必要な JavaScript の実行を待つことなく、即座にページを表示できます。 +- **検索エンジンの最適化とソーシャルネットワークでの共有性**:レンダリングされた HTML は、検索エンジンのボットがページをインデックスするためや、ソーシャルネットワークのボットがページのソーシャルカードプレビューを生成するために使用できます。 +- **ストリーミング**:Server Component により、レンダリング作業をチャンクに分割して、それらが準備できたらクライアントにストリーミングすることができます。これにより、ユーザーはページ全体がサーバーでレンダリングされるのを待たずに、ページの一部を早めに見ることができます。 -## Next.jsでの Server Components の使用 {#using-server-components-in-next-js} +## Next.js における Server Component の使用 {#using-server-components-in-next-js} -デフォルトで、Next.jsは Server Components を使用します。これにより、追加の設定なしでサーバーレンダリングを自動的に実装することができます。必要に応じて Client Components を使用することもできます。[Client Components](/docs/app/building-your-application/rendering/client-components)をご覧ください。 +デフォルトで、Next.js は Server Component を使用します。これにより、追加の設定なしでサーバーレンダリングを自動的に実装できます。必要に応じて Client Component を使用することもできます。詳細は [Client Components](/docs/app/building-your-application/rendering/client-components) を参照してください。 -## Server Components はどのようにレンダリングされますか? {#how-are-server-components-rendered} +## Server Component はどのようにレンダリングされるか? {#how-are-server-components-rendered} -サーバー上で、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントと[サスペンス境界](https://react.dev/reference/react/Suspense)によってチャンクに分割されます。 +サーバー上で、Next.js は React の API を使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントと [Suspense Boundaries](https://react.dev/reference/react/Suspense) によって分割されます。 -各チャンクは2つのステップでレンダリングされます: +それぞれのチャンクは2つのステップでレンダリングされます: -1. Reactは Server Components を**React Server Component Payload (RSC Payload)**という特別なデータ形式にレンダリングします。 -2. Next.jsはRSC Payloadと Client Components のJavaScript命令を使用して、サーバー上で**HTML**をレンダリングします。 +1. React が Server Component を特別なデータ形式、**React Server Component Payload(RSC Payload)**にレンダリングします。 +2. Next.js は RSC Payload と Client Component の JavaScript 命令を使用して、サーバー上で **HTML** をレンダリングします。 -{/* レンダリングの図解 */} +{/* Rendering Diagram */} -次に、クライアント側で以下の順で動作します: +その後、クライアントでは: -1. HTMLは、ルートの素早い非インタラクティブなプレビューを直ちに表示するために使用されます。これは初期ページロード時のみです。 -2. React Server Components Payloadを使用して、クライアントとサーバーのコンポーネントツリーを調整し、DOMを更新します。 -3. JavaScript命令は、 Client Components を[ハイドレート](https://react.dev/reference/react-dom/client/hydrateRoot)してアプリケーションをインタラクティブにします。 +1. HTML を使用して、ルートの迅速な非対話プレビューを即座に表示します。これは初回ページロードに限ります。 +2. React Server Component Payload を使用して、クライアントと Server Component のツリーを一致させ、DOM を更新します。 +3. JavaScript 命令を使用して、Client Component を[ハイドレート](https://react.dev/reference/react-dom/client/hydrateRoot)し、アプリケーションを対話可能にします。 -> #### React Server Component Payload (RSC)とは? +> #### React Server Component Payload (RSC) とは? > -> RSC Payloadは、レンダリングされた React Server Components tree のコンパクトなバイナリ表現です。クライアント上のReactによって、ブラウザのDOMを更新するために使用されます。RSC Payloadには以下が含まれます: +> RSC Payload は、レンダリングされた React Server Components ツリーのコンパクトなバイナリ表現です。クライアント上の React によってブラウザの DOM を更新するために使用されます。RSC Payload には以下が含まれます: > -> - Server Components のレンダリング結果 -> - Client Components がレンダリングされるべき場所のプレースホルダーと、それらのJavaScriptファイルへの参照 -> - Server Component から Client Component に渡される任意のprop +> - Server Component のレンダリング結果 +> - Client Component がレンダリングされるべき場所に対するプレースホルダーと、それらの JavaScript ファイルへの参照 +> - Server Component から Client Component への渡された任意の props ## サーバーレンダリング戦略 {#server-rendering-strategies} -サーバーレンダリングには3つのサブセットがあります:静的、動的、ストリーミングです。 +サーバーレンダリングには、静的、動的、ストリーミングの3つのサブセットがあります。 ### 静的レンダリング(デフォルト) {#static-rendering-default} -静的レンダリングでは、ルートは**ビルド時**または[データの再検証](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)後にバックグラウンドでレンダリングされます。その結果はキャッシュされ、[コンテンツデリバリーネットワーク (CDN)](https://developer.mozilla.org/docs/Glossary/CDN)にプッシュすることができます。この最適化により、レンダリング作業の結果をユーザー間やサーバーリクエスト間で共有できます。 +静的レンダリングでは、ルートは **ビルド時**、または[data や情報の再検証](/docs/app/building-your-application/data-fetching/incremental-static-regeneration) の後、バックグラウンドでレンダリングされます。その結果はキャッシュされ、[コンテンツデリバリーネットワーク(CDN)](https://developer.mozilla.org/docs/Glossary/CDN) にプッシュされることができます。この最適化により、レンダリング作業の結果をユーザー間およびサーバーリクエスト間で共有できます。 -静的レンダリングは、ルートがユーザーにパーソナライズされておらず、ビルド時に知っていることができるデータを持つ場合に有用です。例えば静的なブログ記事や商品ページなどです。 +静的レンダリングは、ルートがユーザーに個別化されておらず、ビルド時にわかるデータ(たとえば、静的なブログポストや製品ページ)の場合に役立ちます。 ### 動的レンダリング {#dynamic-rendering} -動的レンダリングでは、ルートは各ユーザーに対して**リクエスト時**にレンダリングされます。 +動的レンダリングを使用すると、ルートは各ユーザーに対して **リクエスト時** にレンダリングされます。 -動的レンダリングは、ルートがユーザーにパーソナライズされたデータを持つ場合や、キャッシュされていないデータがリクエスト時にしか知られない場合に有用です。たとえば、クッキーやURLの検索パラメーターです。 +動的レンダリングは、ルートがユーザーに個別化されたデータや、リクエスト時にのみわかる情報(たとえばcookieやURLの検索パラメータ)を持つ場合に役立ちます。 -> **キャッシュされたデータを持つ動的ルート** +> **データがキャッシュされた動的ルート** > -> ほとんどのウェブサイトでは、ルートは完全に静的または動的ではなく、その中間スペクトラムです。たとえば、定期的に再検証されるキャッシュされた商品のデータを使用するが、キャッシュされていないパーソナライズされた顧客データも持つeコマースページがあります。 +> 多くのウェブサイトでは、ルートは完全に静的または完全に動的ではなく、それらはスペクトラム上にあります。たとえば、定期的に再確認されるキャッシュされた製品データを使用するものの、キャッシュされていない個別化された顧客データも持つeコマースページがあるかもしれません。 > -> Next.jsでは、キャッシュされたデータとキャッシュされていないデータの両方を持つ動的にレンダリングされたルートを持つことができます。これは、RSC Payloadとデータが別々にキャッシュされるためです。これにより、リクエスト時にすべてのデータを取得することのパフォーマンスへの影響を心配することなく、動的レンダリングに切り替えることができます。 +> Next.js では、キャッシュされたデータとキャッシュされていないデータの両方を持つ動的にレンダリングされたルートを持つことができます。これは、RSC Payload とデータが別々にキャッシュされるためです。これにより、すべてのデータをリクエスト時にフェッチすることによるパフォーマンスへの影響を心配せずに、動的レンダリングを選択することができます。 > -> [完全ルートキャッシュ](/docs/app/building-your-application/caching#full-route-cache)と[データキャッシュ](/docs/app/building-your-application/caching#data-cache)について詳しく学びましょう。 +> [フルルートキャッシュ](/docs/app/building-your-application/caching#full-route-cache)と[データキャッシュ](/docs/app/building-your-application/caching#data-cache)についてさらに学びましょう。 #### 動的レンダリングへの切り替え {#switching-to-dynamic-rendering} -レンダリング中に、[動的API](#dynamic-apis)またはキャッシュされていないデータリクエストが発見されると、Next.jsはそのルート全体を動的にレンダリングするように切り替えます。この表は、動的APIとデータキャッシングがルートが静的または動的にレンダリングされるかどうかにどのように影響するかをまとめたものです: +レンダリング中に、[Dynamic API](#dynamic-apis) または [`fetch`](/docs/app/api-reference/functions/fetch) の `{ cache: 'no-store' }` オプションが発見された場合、Next.js はルート全体の動的レンダリングに切り替えます。以下の表は、Dynamic API とデータキャッシュがルートが静的または動的にレンダリングされるかどうかにどのように影響するかを示しています: -| 動的API | データ | ルート | -| ------- | ------------ | ---------------- | -| なし | キャッシュ | 静的レンダリング | -| あり | キャッシュ | 動的レンダリング | -| なし | 非キャッシュ | 動的レンダリング | -| あり | 非キャッシュ | 動的レンダリング | +| Dynamic APIs | データ | ルート | +| ------------ | -------------- | ---------------- | +| いいえ | キャッシュ済み | 静的レンダリング | +| はい | キャッシュ済み | 動的レンダリング | +| いいえ | キャッシュなし | 動的レンダリング | +| はい | キャッシュなし | 動的レンダリング | -上の表では、ルートが完全に静的であるためには、すべてのデータがキャッシュされていなければなりません。しかし、キャッシュされたデータ取得とキャッシュされていない取得の両方を使用した動的にレンダリングされたルートを持つことができます。 +上記の表では、ルートが完全に静的であるためには、すべてのデータがキャッシュされている必要があります。ただし、キャッシュ済みおよびキャッシュされていないデータフェッチの両方を使用する動的にレンダリングされたルートを持つこともできます。 -開発者として、静的と動的レンダリングのどちらを選ぶ必要はありません。Next.jsは使用される機能とAPIに基づいて各ルートの最適なレンダリング戦略を自動的に選択します。代わりに、[特定のデータをキャッシュする](/docs/app/building-your-application/data-fetching/fetching)か、[再検証する](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)するタイミングを選択し、自分のUIの一部を[ストリーム]することができます。 +開発者として、静的レンダリングと動的レンダリングのどちらを選択する必要はありません。Next.js は、使用される機能や API に基づいて、各ルートに最適なレンダリング戦略を自動的に選択します。代わりに、[特定のデータをキャッシュする](/docs/app/building-your-application/data-fetching/fetching)または[再検証する](/docs/app/building-your-application/data-fetching/incremental-static-regeneration) 時期を選び、UI の一部を[ストリーミング](/docs/app/building-your-application/routing/loading-ui-and-streaming)するかどうかを選ぶことができます。 -### 動的API {#dynamic-apis} +### Dynamic APIs {#dynamic-apis} -動的APIは、事前レンダリング中ではなくリクエスト時にしか知ることができない情報に依存しています。これらのAPIのいずれかを使用することは、開発者の意図を示し、リクエスト時にルート全体を動的レンダリングに移行させます。これらのAPIには以下が含まれます: +Dynamic API は、事前レンダリング中に事前に知ることができない情報に依存します。これらの API のいずれかを使用すると、開発者の意図が示され、リクエスト時にルート全体を動的レンダリングに切り替えることができます。これらの API には次のものが含まれます: - [`cookies`](/docs/app/api-reference/functions/cookies) - [`headers`](/docs/app/api-reference/functions/headers) @@ -109,23 +109,23 @@ React Server Componentsを使用すると、UIをサーバーでレンダリン ### ストリーミング {#streaming} ストリーミング中にルートセグメントを並列化する図。データ取得、レンダリング、および個々のチャンクのハイドレーションを示しています。 -ストリーミングを使用すると、サーバーから段階的にUIをレンダリングできます。作業はチャンクに分割され、準備が整うとクライアントにストリーム配信されます。これにより、全体のコンテンツが完全にレンダリングされる前に、ユーザーが直ちにページの一部を表示できるようになります。 +ストリーミングにより、サーバーから UI を段階的にレンダリングできます。作業はチャンクに分割され、準備ができたらクライアントにストリーミングされます。これにより、ユーザーはコンテンツ全体がレンダリングされる前にページの一部を即座に確認できます。 クライアント上で部分的にレンダリングされたページを示す図。ストリーミングされているチャンクのためのローディングUI。 -ストリーミングは、デフォルトでNext.js App Routerに組み込まれています。これにより、初期ページロードのパフォーマンス向上が図られると同時に、遅いデータ取得に依存してルート全体のレンダリングをブロックするUIも改善します。たとえば、商品のレビューなどです。 +ストリーミングはデフォルトで Next.js の App Router に組み込まれています。これにより、初回ページロードのパフォーマンスと、ルート全体のレンダリングをブロックする遅いデータフェッチに依存する UI の両方を改善できます。たとえば、製品ページのレビューなどです。 -`loading.js`および[React Suspense](/docs/app/building-your-application/routing/loading-ui-and-streaming)を使用してUIコンポーネントとルートセグメントをストリームし始めることができます。詳細は[Loading UI and Streaming](/docs/app/building-your-application/routing/loading-ui-and-streaming)セクションをご覧ください。 +`loading.js` と UI コンポーネントを使用して、ルートセグメントのストリーミングを開始できます。詳細は[Loading UI and Streaming](/docs/app/building-your-application/routing/loading-ui-and-streaming) セクションをご覧ください。 diff --git a/docs/01-app/02-building-your-application/04-caching/index.mdx b/docs/01-app/02-building-your-application/04-caching/index.mdx index b024cc7..3497898 100644 --- a/docs/01-app/02-building-your-application/04-caching/index.mdx +++ b/docs/01-app/02-building-your-application/04-caching/index.mdx @@ -1,64 +1,64 @@ --- -title: 'Next.jsのキャッシュ' +title: 'Next.jsにおけるキャッシュ' nav_title: 'キャッシュ' -description: 'Next.jsにおけるキャッシングメカニズムの概要。' +description: 'Next.jsにおけるキャッシュのメカニズムの概要。' --- -Next.jsは、レンダリング作業やデータリクエストをキャッシュすることで、アプリケーションのパフォーマンスを向上させ、コストを削減します。このページでは、Next.jsのキャッシングメカニズム、またそれらを設定するために使用できるAPI、およびそれらがどのように相互作用するかについて詳しく説明します。 +Next.jsは、レンダリング作業やデータリクエストをキャッシュすることで、アプリケーションのパフォーマンスを向上し、コストを削減します。このページでは、Next.jsのキャッシュメカニズム、設定に使用できるAPI、各メカニズムの相互連携について詳しく説明します。 -> **Good to know**: このページは、Next.jsが内部でどのように動作しているかを理解するのに役立ちますが、Next.jsを生産的に使用するための必須知識ではありません。ほとんどのNext.jsのキャッシングに関するユーリスティックは、APIの使用に基づいて決定され、最小限の設定で最高のパフォーマンスを発揮するためのデフォルトが設定されています。例を見たい場合は、[こちらから始めてください](/docs/app/building-your-application/data-fetching/fetching)。 +> **知っておくと良いこと**: このページは、Next.jsの内部動作を理解するのに役立ちますが、Next.jsを生産的に使うための必須知識では**ありません**。Next.jsのキャッシュヒューリスティックは、主にAPIの使用方法によって決定され、ほとんどの場合ゼロまたは最小限の設定で最適なパフォーマンスを得られるようになっています。代わりに例を見たい場合は、[こちらから始めてください](/docs/app/building-your-application/data-fetching/fetching)。 ## 概要 {#overview} -以下は、さまざまなキャッシングメカニズムとその目的に関する高レベルの概要です: +以下は、さまざまなキャッシュメカニズムとその目的の概要です。 -| メカニズム | 内容 | 場所 | 目的 | 期間 | -| ------------------------------------------- | ------------------- | ------------ | ---------------------------------------------------------- | ------------------------------------ | -| [Request Memoization](#request-memoization) | 関数の戻り値 | サーバー | React Component treeでデータを再利用するため | リクエストライフサイクル中 | -| [Data Cache](#data-cache) | データ | サーバー | ユーザーリクエストやデプロイメント間でデータを保持 | 永続的(再検証可能) | -| [Full Route Cache](#full-route-cache) | HTMLとRSCペイロード | サーバー | レンダリングコストを削減し、パフォーマンスを向上させるため | 永続的(再検証可能) | -| [Router Cache](#client-side-router-cache) | RSCペイロード | クライアント | ナビゲーション時のサーバーリクエストを削減するため | ユーザーセッションまたは時間に基づく | +| メカニズム | 内容 | 場所 | 目的 | 期間 | +| ------------------------------------------- | ----------------------- | ------------ | -------------------------------------------------- | -------------------------------- | +| [Request Memoization](#request-memoization) | 関数の戻り値 | サーバー | React Component treeでデータを再利用 | リクエストライフサイクルの間 | +| [Data Cache](#data-cache) | データ | サーバー | ユーザーリクエストやデプロイをまたいでデータを保存 | 永続的(再検証可能) | +| [Full Route Cache](#full-route-cache) | HTMLおよびRSCペイロード | サーバー | レンダリングコストの削減とパフォーマンス向上 | 永続的(再検証可能) | +| [Router Cache](#client-side-router-cache) | RSCペイロード | クライアント | ナビゲーション時のサーバーリクエスト削減 | ユーザーセッションまたは時間基準 | -Next.jsは、デフォルトでパフォーマンスを向上させコストを削減するために、できる限り多くのキャッシュを行います。つまり、ルートは**静的にレンダリング**され、データリクエストは**キャッシュ**されますが、これは任意で無効にできます。以下のダイアグラムは、ビルド時にルートが静的にレンダリングされるおよび静的なルートが最初に訪れられたときのデフォルトのキャッシング動作を示しています。 +デフォルトで、Next.jsはパフォーマンスを向上し、コストを削減するために可能な限りキャッシュします。つまり、ルートは**静的にレンダリング**され、データリクエストは**キャッシュされます**が、オプトアウトしない限りデフォルトのキャッシュ動作の状態を維持します。下の図は、ビルド時にルートが静的にレンダリングされ、静的ルートが初めてアクセスされたときのデフォルトのキャッシュ動作を示しています。 Next.jsのデフォルトキャッシング動作を示す図で、ビルド時と最初の訪問時のHIT、MISS、SETを示しています。 -キャッシング動作は、ルートが静的か動的か、データがキャッシュされているかされていないか、リクエストが初回訪問の一部なのか後続のナビゲーションによるものかによって変わります。ユースケースに応じて、個々のルートやデータリクエストのキャッシング動作を設定することができます。 +キャッシングの動作は、ルートが静的にレンダリングされるか動的にレンダリングされるか、データがキャッシュされているかされていないか、リクエストが初回訪問の一部であるかそれ以降のナビゲーションの一部であるかによって変わります。ケースによっては、個々のルートおよびデータリクエストのキャッシュ動作を構成できます。 -## リクエストメモ化 {#request-memoization} +## Request Memoization {#request-memoization} -Reactは、同じURLとオプションを持つリクエストを自動的に**メモ化**するために[`fetch` API](#fetch)を拡張しています。これにより、Reactコンポーネントtree内の複数の場所で同じデータを取得するためのfetch関数を呼び出すことができますが、実行されるのは1度だけです。 +Reactは、URLとオプションが同じリクエストを自動的に**メモ化**するように[`fetch` API](#fetch)を拡張します。これは、React component tree内の複数の場所で同じデータに対してfetch関数を呼び出せる一方で、1度だけ実行されることを意味します。 重複排除されたFetchリクエスト -例えば、ルート全体で同じデータが必要な場合(例えば、Layout、Page、および複数のコンポーネントにおいて)、treeの最上部でデータをfetchし、コンポーネント間でpropsを転送する必要はありません。その代わりに、必要なコンポーネント内でデータを取得でき、同じデータに対するネットワーク上での複数リクエストのパフォーマンスへの影響を心配する必要はありません。 +たとえば、ルート全体で同じデータを使用する必要がある場合(例:Layout、Page、および複数のコンポーネント)、ツリーのトップでデータをfetchし、コンポーネント間でpropsを渡す必要はありません。その代わり、必要なコンポーネントでデータをfetchし、同じデータのために複数のネットワークリクエストを作成するパフォーマンスへの影響を考慮する必要はありません。 ```tsx title="app/example.tsx" switcher async function getItem() { - // `fetch`関数は自動的にメモ化され、その結果はキャッシュされます + // `fetch`関数は自動的にメモ化され、結果がキャッシュされます const res = await fetch('https://.../item/1') return res.json() } -// この関数は2回呼び出されますが、最初の1回のみ実行されます +// この関数は2回呼ばれますが、最初にのみ実行されます const item = await getItem() // cache MISS -// 二度目の呼び出しはルート内のどこでも可能です +// 2番目の呼び出しはルート内のどこでも可能です const item = await getItem() // cache HIT ``` @@ -67,319 +67,319 @@ const item = await getItem() // cache HIT ```jsx title="app/example.js" switcher async function getItem() { - // `fetch`関数は自動的にメモ化され、その結果はキャッシュされます + // `fetch`関数は自動的にメモ化され、結果がキャッシュされます const res = await fetch('https://.../item/1') return res.json() } -// この関数は2回呼び出されますが、最初の1回のみ実行されます +// この関数は2回呼ばれますが、最初にのみ実行されます const item = await getItem() // cache MISS -// 二度目の呼び出しはルート内のどこでも可能です +// 2番目の呼び出しはルート内のどこでも可能です const item = await getItem() // cache HIT ``` -**リクエストメモ化の仕組み** +**Request Memoizationの仕組み** Reactレンダリング中にfetchメモ化がどのように機能するかを示すダイアグラム。 -- ルートをレンダリングする際に、特定のリクエストが初めて呼び出されたとき、その結果はメモリに存在せず、キャッシュの`MISS`となります。 -- したがって、関数が実行され、データが外部ソースから取得され、その結果がメモリに格納されます。 -- 同じレンダーパス内でのリクエストの後続の関数呼び出しはキャッシュの`HIT`となり、関数を実行することなくメモリからデータが返されます。 -- ルートがレンダリングされ、レンダリングパスが完了すると、メモリは「リセット」され、すべてのリクエストメモ化エントリがクリアされます。 +- ルートをレンダリングする際、特定のリクエストが初めて呼び出された場合、その結果はメモリに存在せず、キャッシュ`MISS`となります。 +- したがって、関数が実行され、データが外部ソースから取得され、その結果はメモリに保存されます。 +- 同じレンダーパス内で同じリクエストの後続の関数呼び出しはキャッシュ`HIT`となり、関数を実行することなくメモリからデータが返されます。 +- ルートがレンダリングされ、レンダリングパスが完了した後、メモリは「リセット」され、すべてのリクエストメモ化エントリがクリアされます。 -> **Good to know**: +> **知っておくと良いこと**: > -> - リクエストメモ化はReactの機能であり、Next.jsの機能ではありません。ここでは、他のキャッシングメカニズムとの相互作用を示すために含まれています。 -> - メモ化は`fetch`リクエストの`GET`メソッドにのみ適用されます。 -> - メモ化はReact Component treeにのみ適用されます。つまり: -> - `generateMetadata`、`generateStaticParams`、Layouts、Pages、およびその他のServer Components内の`fetch`リクエストに適用されます。 -> - Route Handlers内の`fetch`リクエストには適用されません。なぜなら、それらはReact component treeの一部ではないからです。 -> - `fetch`が適さない場合(例:一部のデータベースクライアント、CMSクライアント、GraphQLクライアント)、関数をメモ化するために[Reactの`cache`関数](#react-cache-function)を使用できます。 +> - Request memoizationはReactの機能であり、Next.jsの機能ではありません。他のキャッシングメカニズムとの相互作用を示すためにここに含まれています。 +> - メモ化は`GET`メソッドの`fetch`リクエストにのみ適用されます。 +> - メモ化はReact Component treeにのみ適用されます。つまり: +> - `fetch`リクエストは`generateMetadata`、`generateStaticParams`、Layouts、Pages、およびその他のServer Componentsに適用されます。 +> - Route Handlersの`fetch`リクエストには適用されません。これらはReact component treeの一部ではありません。 +> - `fetch`が適さない場合(例: 一部のデータベースクライアント、CMSクライアント、またはGraphQLクライアント)、[React `cache`関数](#react-cache-function)を使用して関数をメモ化できます。 ### 期間 {#duration} -キャッシュはサーバーリクエストのライフタイムが続く間、つまりReact component treeのレンダリングが完了するまで持続します。 +キャッシュは、サーバーリクエストのライフタイム、React componente treeのレンダリングが終了するまで持続します。 ### 再検証 {#revalidating} -メモ化はサーバーリクエスト間で共有されず、レンダリング中のみに適用されるため、再検証する必要はありません。 +メモ化はサーバーリクエストをまたいで共有されず、レンダリング中にのみ適用されるため、それを再検証する必要はありません。 ### オプトアウト {#opting-out} -メモ化は`fetch`リクエストの`GET`メソッドにのみ適用され、`POST`や`DELETE`などの他のメソッドはメモ化されません。このデフォルトの動作はReactの最適化であり、オプトアウトすることをお勧めしません。 +メモ化は`fetch`リクエストの`GET`メソッドにのみ適用され、`POST`や`DELETE`などの他のメソッドはメモ化されません。このデフォルトの動作はReactの最適化であり、これからのオプトアウトを推奨しません。 -個々のリクエストを管理するには、[`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)の[`signal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal)プロパティを使用できます。ただし、これはメモ化からオプトアウトするのではなく、実行中のリクエストを中止するものです。 +個々のリクエストを管理するには、[`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)から[`signal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal)プロパティを使用できます。ただし、これはリクエストのメモ化をオプトアウトするのではなく、飛行中のリクエストを中止することになります。 ```js title="app/example.js" const { signal } = new AbortController() fetch(url, { signal }) ``` -## データキャッシュ {#data-cache} +## Data Cache {#data-cache} -Next.jsには組み込みのデータキャッシュがあり、データの取得結果を**サーバーリクエスト**と**デプロイメント**間で**保持**します。これは、Next.jsがネイティブの`fetch` APIを拡張し、サーバー上の各リクエストが独自の永続的なキャッシングセマンティクスを設定できるようにすることで可能です。 +Next.jsには、データフェッチの結果を**保持**する組み込みのData Cacheがあります。**サーバーリクエスト**または**デプロイ**をまたいで保持します。これは、Next.jsがネイティブの`fetch` APIを拡張して、サーバーの各リクエストが独自の永続的なキャッシングセマンティクスを設定できるようにすることによって実現されています。 -> **Good to know**: ブラウザでは、`fetch`の`cache`オプションはリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示しますが、Next.jsでは、`cache`オプションはサーバー側のリクエストがサーバーのデータキャッシュとどのように相互作用するかを示します。 +> **知っておくと良いこと**: ブラウザでは、`fetch`の`cache`オプションがリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示しますが、Next.jsでは、`cache`オプションがサーバー側のリクエストがサーバーのData Cacheとどのように相互作用するかを示します。 -`fetch`の[`cache`](#fetch-optionscache)および[`next.revalidate`](#fetch-optionsnextrevalidate)オプションを使用して、キャッシング動作を設定できます。 +`fetch`の[`cache`](#fetch-optionscache)と[`next.revalidate`](#fetch-optionsnextrevalidate)オプションを使用して、キャッシュ動作を構成できます。 -**データキャッシュの仕組み** +**Data Cacheの仕組み** データキャッシュと対話するキャッシュおよび非キャッシュのfetchリクエストの図。キャッシュリクエストはデータキャッシュに格納され、メモ化されます。非キャッシュリクエストはデータソースから取得され、データキャッシュに格納されず、メモ化されます。 -- `'force-cache'`オプション付きの`fetch`リクエストがレンダリング中に初めて呼び出されたとき、Next.jsはデータキャッシュにキャッシュされた応答があるか確認します。 -- キャッシュされた応答が見つかった場合、それはすぐに返され、[メモ化されます](#request-memoization)。 -- キャッシュされた応答が見つからなかった場合、リクエストがデータソースに送られ、その結果がデータキャッシュに保存され、メモ化されます。 -- 非キャッシュデータ(例:`cache`オプションが定義されていないまたは`{ cache: 'no-store' }`を使用)は、結果が常にデータソースから取得され、メモ化されます。 -- データがキャッシュされているかどうかにかかわらず、同じデータに対する重複したリクエストを防ぐためにリクエストは常にメモ化され、Reactレンダリングパス中に行われます。 +- `'force-cache'`オプション付きの`fetch`リクエストがレンダリング中に初めて呼び出された場合、Next.jsはData Cacheにキャッシュされたレスポンスを探します。 +- キャッシュされたレスポンスが見つかった場合、それはすぐに返され、[メモ化されます](#request-memoization)。 +- キャッシュされたレスポンスが見つからない場合、リクエストはデータソースに送信され、その結果がData Cacheに保存され、メモ化されます。 +- キャッシュされていないデータ(例: `cache`オプションが定義されていない、または`{ cache: 'no-store' }`を使用している場合)、結果は常にデータソースから取得され、メモ化されます。 +- データがキャッシュされているかされていないかに関係なく、リクエストは常にメモ化され、Reactのレンダリングパス中に同じデータのための重複リクエストを避けるようにします。 -> **データキャッシュとリクエストメモ化の違い** +> **Data CacheとRequest Memoizationの違い** > -> 両方のキャッシングメカニズムは、キャッシュされたデータを再利用することによってパフォーマンスを向上させますが、データキャッシュはリクエストとデプロイメントにまたがって永続的に維持されるのに対し、メモ化はリクエストのライフタイム内でのみ持続します。 +> どちらのキャッシングメカニズムもキャッシュされたデータの再利用によってパフォーマンスを向上させるのに役立ちますが、Data Cacheはリクエストやデプロイをまたいで永続的であるのに対し、メモ化はリクエストの期間中のみ持続します。 ### 期間 {#duration} -データキャッシュは、再検証またはオプトアウトが行われない限り、リクエストやデプロイメント間で永続的に保持されます。 +Data Cacheはリクエストをまたいで永続的です。再検証しない限り、またはオプトアウトする限り。 ### 再検証 {#revalidating} -キャッシュされたデータは次の2つの方法で再検証できます: +キャッシュされたデータは、以下の2つの方法で再検証できます。 -- **時間ベースの再検証**: 一定時間経過後の新しいリクエストでデータを再検証します。これは、データがあまり頻繁に変化せず、新鮮さがあまり重要でない場合に有用です。 -- **オンデマンドの再検証**: イベントに基づいてデータを再検証します(例:フォーム送信)。オンデマンドの再検証はタグベースまたはパスベースのアプローチを使用してデータのグループを一度に再検証できます。例えば、無頭CMSのコンテンツが更新されたときに最新のデータをすぐに表示したい場合に有効です。 +- **時間に基づく再検証**:一定の時間が経過した後に新しいリクエストを行う際にデータを再検証します。これは変更が少ないデータや刷新性がそれほど重要でないデータに対して便利です。 +- **オンデマンド再検証**:イベントに基づいてデータを再検証します(例:フォーム送信)。オンデマンド再検証は、タグベースまたはパスベースのアプローチを使用してデータのグループを一度に再検証できます。これは、ヘッドレスCMSからのコンテンツが更新されたときに最新のデータを可能な限り早く表示したい場合に便利です。 -#### 時間ベースの再検証 {#time-based-revalidation} +#### 時間に基づく再検証 {#time-based-revalidation} -特定の時間間隔でデータを再検証するには、`fetch`における`next.revalidate`オプションを使用して、リソースのキャッシュライフタイム(秒単位)を設定します。 +定期的にデータを再検証するには、`fetch`の`next.revalidate`オプションを使用して、リソースのキャッシュ寿命(秒)を設定します。 ```js -// 最大で毎時再生性を検証 +// 最大1時間ごとに再検証 fetch('https://...', { next: { revalidate: 3600 } }) ``` -または、[ルートセグメント設定オプション](#segment-config-options)を使用して、セグメント内のすべての`fetch`リクエストを設定したり、`fetch`を使用できない場合に設定できます。 +または、[Route Segment Configオプション](#segment-config-options)を使用して、セグメント内のすべての`fetch`リクエストを設定するか、`fetch`が使用できない場合に利用可能です。 -**時間ベースの再検証の仕組み** +**時間に基づく再検証の仕組み** 時間ベースの再検証の仕組みを示す図で、再検証期間後、最初のリクエストに対して古いデータが返され、次にデータが再検証されます。 -- `fetch`リクエストが最初に`revalidate`を指定して呼び出されたとき、外部データソースからデータが取得され、データキャッシュに保存されます。 -- 指定された時間枠内に呼び出されたリクエストは、キャッシュされたデータを返します。 -- 時間枠が経過した後、次のリクエストはまだキャッシュ(現在は古い)データを返します。 +- `revalidate`を含むfetchリクエストが初めて呼び出されると、データは外部データソースから取得され、Data Cacheに保存されます。 +- 指定された期間内(例: 60秒)に呼び出されたリクエストは、キャッシュされたデータを返します。 +- 期間が経過した後、次のリクエストは依然として古い(期限切れ)データを返します。 - Next.jsはバックグラウンドでデータの再検証をトリガーします。 - - データが正常に取得されると、Next.jsは新鮮なデータでデータキャッシュを更新します。 - - バックグラウンド再検証が失敗した場合、前のデータはそのまま残ります。 + - データの取得が成功すると、Next.jsは新しいデータでData Cacheを更新します。 + - バックグラウンドでの再検証に失敗した場合、以前のデータはそのまま保持されます。 -これは[**stale-while-revalidate**](https://web.dev/stale-while-revalidate/)動作に似ています。 +これは[**stale-while-revalidate**](https://web.dev/stale-while-revalidate/)に似た動作です。 #### オンデマンド再検証 {#on-demand-revalidation} -データはパスごとに([`revalidatePath`](#revalidatepath))またはキャッシュタグごとに([`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag))オンデマンドで再検証できます。 +データは、パス([`revalidatePath`](#revalidatepath))またはキャッシュタグ([`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag))によってオンデマンドで再検証できます。 **オンデマンド再検証の仕組み** オンデマンド再検証の仕組みを示す図で、データキャッシュが再検証リクエスト後に新鮮なデータで更新される仕組みを示します。 -- `fetch`リクエストが初めて呼び出されたとき、データが外部データソースから取得され、データキャッシュに保存されます。 -- オンデマンド再検証がトリガーされると、適切なキャッシュエントリはキャッシュから削除されます。 - - これは、古いデータをキャッシュに保持する時間ベースの再検証とは異なり、データが取得されるまでキャッシュに残ります。 -- 次回のリクエストが行われたとき、再びキャッシュの`MISS`となり、データが外部データソースから取得され、データキャッシュに保存されます。 +- 初めて`fetch`リクエストが呼び出されると、データは外部データソースから取得され、Data Cacheに保存されます。 +- オンデマンド再検証がトリガーされると、適切なキャッシュエントリがキャッシュから削除されます。 + - これは、期間に基づく再検証とは異なり、新しいデータが取得されるまで古いデータをキャッシュに保持する再検証とは異なります。 +- 次にリクエストが行われたとき、それは再びキャッシュ`MISS`となり、データは外部データソースから取得され、Data Cacheに保存されます。 ### オプトアウト {#opting-out} -`fetch`からの応答をキャッシュしたくない場合、以下のようにできます: +`fetch`からのレスポンスをキャッシュしたくない場合は、次のことができます。 ```js let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' }) ``` -## フルルートキャッシュ {#full-route-cache} +## Full Route Cache {#full-route-cache} -> **関連する用語**: +> **関連用語**: > -> 自動静的最適化、静的サイト生成、または静的レンダリングという用語が、アプリケーションのルートをビルド時にレンダリングおよびキャッシュするプロセスを指すために互換的に使用されることがあります。 +> **Automatic Static Optimization**、**Static Site Generation**、および**Static Rendering**の用語が、アプリケーションのルートをビルド時にレンダリングおよびキャッシュするプロセスを指して互換的に使用される場合があります。 -Next.jsはデフォルトでルートをビルドタイムにレンダリングし、キャッシュします。これは、個々のリクエストごとにサーバーでレンダリングする代わりにキャッシュされたルートを提供できる最適化であり、高速なページ読み込みを実現します。 +Next.jsは、自動的にルートをレンダリングし、ビルド時にキャッシュします。これは最適化であり、各リクエストごとにサーバーでレンダリングする代わりにキャッシュされたルートを提供することで、ページロードを高速化します。 -フルルートキャッシュがどのように機能するかを理解するために、Reactがレンダリングをどのように扱うか、およびNext.jsがその結果をどのようにキャッシュするかを見ると役立ちます: +Full Route Cacheの仕組みを理解するためには、Reactがレンダリングをどのように処理するか、およびNext.jsがどのように結果をキャッシュするかを見てみるのが役立ちます。 -### 1. サーバーにおけるReactレンダリング {#1-react-rendering-on-the-server} +### 1. サーバーでのReactレンダリング {#1-react-rendering-on-the-server} -サーバーでは、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントおよびSuspenseバウンダリーごとに分割されます。 +サーバー上で、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントやSuspense境界によってチャンクに分割されます。 -各チャンクは2つのステップでレンダリングされます: +各チャンクは2つのステップでレンダリングされます。 -1. ReactはServer Componentsをストリーミングに最適化された特別なデータフォーマットにレンダリングします。これは**React Server Component Payload**と呼ばれます。 -2. Next.jsはReact Server Component PayloadとクライアントのJavaScript命令を使用して、サーバー上で**HTML**をレンダリングします。 +1. ReactはServer Componentsをストリーミングに最適化された特殊なデータ形式、**React Server Component Payload**にレンダリングします。 +2. Next.jsは、React Server Component PayloadおよびClient ComponentのJavaScript命令を使用して、サーバー上で**HTML**をレンダリングします。 -これにより、すべてがレンダリングされるのを待たずに作業をキャッシュしたり、応答を送信することができます。代わりに、作業が完了するたびに応答をストリーミングできるようになります。 +これにより、すべてをレンダリングし終わるのを待つことなく作業をキャッシュしたり、レスポンスを送信することが可能になります。代わりに、作業が完了するごとに結果をストリームできます。 -> **React Server Component Payloadとは何か?** +> **React Server Component Payloadとは** > -> React Server Component Payloadは、レンダリングされたReact Server Components treeのコンパクトなバイナリ表現です。クライアント上のReactにより、ブラウザのDOMを更新するために使用されます。React Server Component Payloadには以下が含まれます: +> React Server Component Payloadは、レンダリングされたReact Server Components treeのコンパクトなバイナリ表現です。これはクライアントでReactがブラウザのDOMを更新するために使用されます。React Server Component Payloadには次のものが含まれます。 > -> - Server Componentsのレンダリング結果 -> - クライアント ComponentsのJavaScriptファイルのプレースホルダーとその参照 -> - Server Componentsからクライアント Componentsに渡されたprops +> - Server Componentsのレンダリングされた結果 +> - Client Componentsがレンダリングされる場所のプレースホルダーとそれらのJavaScriptファイルへの参照 +> - Server ComponentからClient Componentに渡されるprops > -> 詳細は、[Server Components](/docs/app/building-your-application/rendering/server-components)のドキュメントをご覧ください。 +> 詳しくは、[Server Components](/docs/app/building-your-application/rendering/server-components)のドキュメントをご覧ください。 -### 2. サーバーでのNext.jsキャッシング(フルルートキャッシュ) {#2-next-js-caching-on-the-server-full-route-cache} +### 2. サーバーでのNext.jsキャッシュ(Full Route Cache) {#2-next-js-caching-on-the-server-full-route-cache} Next.jsのデフォルトのフルルートキャッシュの動作を示しており、React Server Component PayloadとHTMLがサーバーでキャッシュされる様子を示しています。 -Next.jsのデフォルトの動作は、ルートのレンダリング結果(React Server Component PayloadとHTML)をサーバーでキャッシュすることです。これはビルドタイムや再検証時に静的にレンダリングされたルートに適用されます。 +Next.jsのデフォルトの動作は、ルートのレンダリング結果(React Server Component PayloadとHTML)をサーバーにキャッシュすることです。これは、ビルド時または再検証中に静的にレンダリングされるルートに適用されます。 -### 3. クライアントでのReact実行と同期 {#3-react-hydration-and-reconciliation-on-the-client} +### 3. クライアントでのReactのハイドレーションと和解 {#3-react-hydration-and-reconciliation-on-the-client} -リクエスト時にクライアントでは: +リクエスト時、クライアントで次の手順が行われます。 -1. HTMLは、クライアントとServer Componentsの非対話型の初期プレビューをすぐに表示するために使用されます。 -2. React Server Components Payloadは、クライアントとレンダリングされたServer Component treesを統合して、DOMを更新するために使用されます。 -3. JavaScript命令は、クライアント Componentsを[実行](https://react.dev/reference/react-dom/client/hydrateRoot)してアプリケーションを対話型にします。 +1. HTMLは、クライアントとServer Componentsのインタラクティブではない初期プレビューを高速に表示するために使用されます。 +2. React Server Components Payloadは、クライアントとレンダリングされたServer Component treesを調和し、DOMを更新するために使用されます。 +3. JavaScript命令は、クライアントコンポーネントを[ハイドレーション](https://react.dev/reference/react-dom/client/hydrateRoot)し、アプリケーションをインタラクティブにします。 -### 4. クライアントでのNext.jsキャッシング(ルーターキャッシュ) {#4-next-js-caching-on-the-client-router-cache} +### 4. クライアントでのNext.jsキャッシュ(Router Cache) {#4-next-js-caching-on-the-client-router-cache} -React Server Component Payloadは、クライアント側の[Router Cache](#client-side-router-cache)に格納されます。これは、個々のルートセグメントごとに分割されたメモリキャッシュです。このRouter Cacheは、以前に訪問したルートを保存し、将来的に訪問する可能性のあるルートを事前に取得するために使用されます。 +React Server Components Payloadは、ルートセグメントごとに分割されたクライアント側の[Router Cache](#client-side-router-cache)に保存されます。このRouter Cacheは、以前に訪問したルートを保存したり、将来のルートをプリフェッチすることで、ナビゲーション体験を向上させるために使用されます。 ### 5. 後続のナビゲーション {#5-subsequent-navigations} -後続のナビゲーションや事前取得中、Next.jsはRouter CacheにReact Server Components Payloadが保存されているかどうかを確認します。保存されている場合は、新しいサーバーリクエストを送信することをスキップします。 +後続のナビゲーション時またはプリフェッチ中、Next.jsはReact Server Components PayloadがRouter Cacheに保存されているかを確認します。もしそうなら、新しいリクエストをサーバーに送信するのをスキップします。 -ルートセグメントがキャッシュにない場合、Next.jsはサーバーからReact Server Components Payloadを取得し、クライアントのRouter Cacheに追加します。 +ルートセグメントがキャッシュにない場合、Next.jsはReact Server Components Payloadをサーバーからフェッチし、クライアントのRouter Cacheを更新します。 -### 静的と動的レンダリング {#static-and-dynamic-rendering} +### 静的レンダリングと動的レンダリング {#static-and-dynamic-rendering} -ルートがビルドタイムにキャッシュされるかどうかは、そのルートが静的または動的にレンダリングされるかどうかに依存します。静的ルートはデフォルトでキャッシュされ、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。 +ルートがビルド時にキャッシュされるかどうかは、それが静的にレンダリングされるか動的にレンダリングされるかによります。静的ルートはデフォルトでキャッシュされ、動的ルートはリクエスト時にレンダリングされ、キャッシュされない。 -以下の図は、静的および動的にレンダリングされたルートの違いを示しており、キャッシュデータと非キャッシュデータが示されています: +この図は、キャッシュされたデータとキャッシュされていないデータを使用して、静的および動的にレンダリングされたルートの違いを示しています。 静的および動的レンダリングがフルルートキャッシュに与える影響を示す図。静的ルートはビルドタイムまたはデータ再検証後にキャッシュされ、動的ルートは決してキャッシュされない。 -[静的および動的レンダリング](/docs/app/building-your-application/rendering/server-components#server-rendering-strategies)について詳しく学ぶ。 +[静的レンダリングと動的レンダリング](/docs/app/building-your-application/rendering/server-components#server-rendering-strategies)の詳細を学びます。 ### 期間 {#duration} -デフォルトでは、フルルートキャッシュは永続的です。これは、レンダー出力がユーザーリクエスト間でキャッシュされることを意味します。 +デフォルトで、Full Route Cacheは永続的です。つまり、レンダリング出力はユーザーリクエストをまたいでキャッシュされます。 ### 無効化 {#invalidation} -フルルートキャッシュを無効化する方法は2つあります: +Full Route Cacheを無効化する方法は2つあります。 -- **[データの再検証](/docs/app/building-your-application/caching#revalidating)**: データキャッシュを再検証すると、サーバー上でコンポーネントが再レンダリングされ、新しいレンダー出力がキャッシュされることでRouter Cacheも無効化されます。 -- **再デプロイ**: データキャッシュとは異なり、フルルートキャッシュは新しいデプロイメント時にクリアされます。 +- **[データの再検証](/docs/app/building-your-application/caching#revalidating)**: [Data Cache](#data-cache)を再検証することで、[Router Cache](#client-side-router-cache)を無効化し、サーバーでコンポーネントを再レンダリングし、新しいレンダリング結果をキャッシュします。 +- **再デプロイ**: Data Cacheとは異なり、デプロイをまたいで永続するFull Route Cacheは、新しいデプロイ時にクリアされます。 ### オプトアウト {#opting-out} -フルルートキャッシュからオプトアウトすることができます。言い換えれば、各インカミングリクエストごとにコンポーネントを動的にレンダリングすることができます: +Full Route Cache、または別の言い方をすると、各リクエストごとに動的にコンポーネントをレンダリングすることからオプトアウトすることができます。 -- **[動的API](#dynamic-apis)の使用**: これはフルルートキャッシュからルートをオプトアウトし、リクエスト時に動的にレンダリングされることを意味します。データキャッシュは依然として使用できます。 -- ** `dynamic = 'force-dynamic'`または`revalidate = 0` ルートセグメント設定オプションを使用する**: これはフルルートキャッシュおよびデータキャッシュをスキップします。つまり、インカミングリクエストごとにサーバー上でコンポーネントがレンダリングされ、データが取得されます。ルートキャッシュはクライアント側のキャッシュであるため引き続き適用されます。 -- **[データキャッシュ](#data-cache)のオプトアウト**: `fetch`リクエストでキャッシュされないものがある場合、そのルートはフルルートキャッシュからオプトアウトします。特定の`fetch`リクエストに対して、インカミングリクエストごとにデータが取得されます。キャッシュオプトアウトしないその他の`fetch`リクエストは依然としてデータキャッシュにキャッシュされ続けます。これは、キャッシュされたデータとキャッシュされていないデータが共存するハイブリッドを可能にします。 +- **[Dynamic API](#dynamic-apis)を使用する**: これにより、ルートはFull Route Cacheからオプトアウトされ、リクエスト時に動的にレンダリングされます。Data Cacheは引き続き使用できます。 +- **`dynamic = 'force-dynamic'`または`revalidate = 0`ルートセグメント構成オプションを使用する**: これにより、Full Route CacheとData Cacheをスキップします。つまり、すべての受信リクエストでコンポーネントがレンダリングされ、データがフェッチされます。ただし、Router Cacheはクライアント側のキャッシュであるため、依然として適用されます。 +- **[Data Cache](#data-cache)からのオプトアウト**: `fetch`リクエストがキャッシュされないルートがある場合、このルートはFull Route Cacheからオプトアウトされます。特定の`fetch`リクエストのデータは、受信リクエストごとにフェッチされます。他のキャッシュからのオプトアウトを選択しない`fetch`リクエストは、Data Cacheにキャッシュされます。これにより、キャッシュされたデータとキャッシュされていないデータのハイブリッドが可能になります。 -## クライアントサイドのルーターキャッシュ {#client-side-router-cache} +## クライアント側のRouter Cache {#client-side-router-cache} -Next.jsには、レイアウト、読み込み状態、ページごとに分割されたルートセグメントのRSCペイロードを格納するメモリ内クライアントサイドルーターキャッシュがあります。 +Next.jsにはメモリ内のクライアント側ルーターキャッシュがあります。これは、レイアウト、読み込み状態、ページに分割されたルートセグメントのRSCペイロードを保存します。 -ユーザーがルート間を移動するとき、Next.jsは訪問したルートセグメントをキャッシュし、ユーザーが訪問する可能性があるルートを[事前取得](/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)します。これにより、瞬時のバック/フォワードナビゲーション、ナビゲーション間の全ページ更新の不要、React状態やブラウザ状態の保持が実現されます。 +ユーザーがルート間を移動するとき、Next.jsは訪れたルートセグメントをキャッシュし、ユーザーが移動する可能性のあるルートを[prefetch](/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)します。これにより、瞬時の戻る/進むナビゲーションが行われ、ナビゲーション間でのフルページリロードがなく、Reactとブラウザの状態が保持されます。 -ルーターキャッシュを使用することで: +Router Cacheの利用により: -- **レイアウト**はキャッシュされ、ナビゲーション時に再利用されます([部分レンダリング](/docs/app/building-your-application/routing/linking-and-navigating#4-partial-rendering))。 -- **読み込み状態**はルート間の瞬時のナビゲーションのためにキャッシュされ再利用されます([瞬時読み込み状態](/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states))。 -- **ページ** はデフォルトでキャッシュされませんが、ブラウザの前後のナビゲーション時に再利用されます。[実験オプション`staleTimes`](/docs/app/api-reference/config/next-config-js/staleTimes)を使ってページセグメントをキャッシュすることができます。 +- **Layouts**はキャッシュされ、[部分的なレンダリング](/docs/app/building-your-application/routing/linking-and-navigating#4-partial-rendering)でナビゲーション時に再利用されます +- **読み込み状態**はキャッシュされ、ナビゲーション時に[瞬時のナビゲーション](/docs/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states)用に再利用されます +- **Pages**はデフォルトではキャッシュされませんが、ブラウザの後方および前方のナビゲーション中に再利用されます。ページセグメントのキャッシングを有効にするには、実験的な[`staleTimes`](/docs/app/api-reference/config/next-config-js/staleTimes)構成オプションを使用します {/* TODO: 図をv15の動作に合わせて更新する */} -> **Good to know:** このキャッシュはNext.jsとServer Componentsに特有であり、ブラウザの[bfcache](https://web.dev/bfcache/)とは異なりますが、似たような結果をもたらします。 +> **知っておくと良いこと**: このキャッシュはNext.jsとServer Componentsに特有のものであり、ブラウザの[bfcache](https://web.dev/bfcache/)とは異なりますが、類似した結果をもたらします ### 期間 {#duration} -キャッシュはブラウザの一時メモリに格納されます。2つの要因がルーターキャッシュの存続期間を決定します: +キャッシュはブラウザの一時的なメモリに保存されます。Router Cacheの持続期間を決定する要素は2つあります。 -- **セッション**: ナビゲーション中にキャッシュは持続します。ただし、ページの再読み込みでクリアされます。 -- **自動無効化期間**: レイアウトと読み込み状態のキャッシュは、指定された時間後に自動的に無効化されます。期間は、リソースがどのように[事前取得された](/docs/app/api-reference/components/link#prefetch)か、そしてリソースが[静的に生成された](/docs/app/building-your-application/rendering/server-components#static-rendering-default)かに依存します: - - **デフォルトの事前取得**(`prefetch={null}`または指定なし): 動的ページにはキャッシュされません、静的ページには5分間。 - - **完全な事前取得**(`prefetch={true}`または`router.prefetch`): 静的および動的ページの両方に対して5分間。 +- **セッション**: キャッシュはナビゲーション間で持続しますが、ページのリフレッシュ時にクリアされます +- **自動無効化期間**: レイアウトと読み込み状態のキャッシュは特定の時間の後に自動的に無効化されます。リソースが[プリフェッチ](/docs/app/api-reference/components/link#prefetch)された方法、そのリソースが[静的に生成](/docs/app/building-your-application/rendering/server-components#static-rendering-default)されたかによって期間は決まります。 + - **デフォルトのプリフェッチ**(`prefetch={null}`または未指定): 動的ページではキャッシュされず、静的ページでは5分間 + - **完全なプリフェッチ**(`prefetch={true}`または`router.prefetch`): 静的および動的ページのどちらも5分間 -ページの再読み込みは**すべて**のキャッシュセグメントをクリアしますが、自動無効化期間は、事前取得された時間からの個々のセグメントのみに影響します。 +ページのリフレッシュによりすべてのキャッシュされたセグメントが消去されますが、自動無効化期間はプリフェッチされたときからの個々のセグメントにのみ影響を与えます。 -> **Good to know**: 実験オプション[`staleTimes`](/docs/app/api-reference/config/next-config-js/staleTimes)を使用して上記の自動無効化時間を調整することができます。 +> **知っておくと良いこと**: 実験的な[`staleTimes`](/docs/app/api-reference/config/next-config-js/staleTimes)構成オプションを使用して、上記の自動無効化時間を調整できます。 ### 無効化 {#invalidation} -ルーターキャッシュを無効化する方法は次の2つです: +Router Cacheを無効化する方法は2つあります。 -- **Server Action** の中で: - - パスでのオンデマンド再検証は([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath))タグでのキャッシュ再検証は([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)) - - [`cookies.set`](/docs/app/api-reference/functions/cookies#setting-a-cookie)または[`cookies.delete`](/docs/app/api-reference/functions/cookies#deleting-cookies)を使用してルーターキャッシュを無効にし、クッキーを使用するルートが古くなるのを防ぐ(例:認証)。 -- [`router.refresh`](/docs/app/api-reference/functions/use-router)を呼び出すことでルーターキャッシュを無効にし、現在のルートに対するサーバーへの新しいリクエストを行う。 +- **Server Action**で: + - パスによってオンデマンドでデータを再検証([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath))またはキャッシュタグで([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)) + - [`cookies.set`](/docs/app/api-reference/functions/cookies#setting-a-cookie)または[`cookies.delete`](/docs/app/api-reference/functions/cookies#deleting-cookies)の使用により、cookiesを使用するルートが古くならないようにRouter Cacheを無効化(例:認証) +- [`router.refresh`](/docs/app/api-reference/functions/use-router)を呼び出すことでRouter Cacheを無効化し、現在のルートのサーバーへの新しいリクエストを行います。 ### オプトアウト {#opting-out} Next.js 15以降、ページセグメントはデフォルトでオプトアウトされています。 -> **Good to know:** ``コンポーネントの`prefetch`プロップを`false`に設定することで、[事前取得](/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)をオプトアウトすることもできます。 +> **知っておくと良いこと**: また、`prefetch`プロップを``コンポーネントに対して`false`に設定することで、[prefetch](/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)からもオプトアウトできます。 ## キャッシュの相互作用 {#cache-interactions} -さまざまなキャッシングメカニズムを設定する際、相互作用を理解することが重要です: +さまざまなキャッシュメカニズムを設定する際に、相互作用の仕方を理解することは重要です。 -### データキャッシュとフルルートキャッシュ {#data-cache-and-full-route-cache} +### Data CacheとFull Route Cache {#data-cache-and-full-route-cache} -- データキャッシュを再検証またはオプトアウトすることは、フルルートキャッシュを無効化します。なぜなら、レンダー出力はデータに依存しているからです。 -- フルルートキャッシュを無効化またはオプトアウトしても、データキャッシュには影響しません。キャッシュされたデータとキャッシュされていないデータの両方を持つルートを動的にレンダリングできます。たとえば、ほとんどのページがキャッシュされたデータを使用する場合でも、いくつかのコンポーネントがリクエスト時に取得する必要のあるデータに依存していることに有用です。すべてのデータを再取得する際のパフォーマンスへの影響を心配せずに動的レンダリングできます。 +- Data Cacheの再検証またはオプトアウトにより、レンダリング出力がデータに依存するため、Full Route Cacheを無効化します。 +- Full Route Cacheの無効化またはオプトアウトは、Data Cacheには影響しません。キャッシュされたデータとキャッシュされていないデータの両方を持つ動的なルートをレンダリングすることができます。これはページのほとんどがキャッシュされたデータを使用し、一部のコンポーネントがリクエスト時にフェッチするデータに依存する場合に役立ちます。すべてのデータを再フェッチすることによるパフォーマンスの影響を気にせずに動的レンダリングが可能です。 -### データキャッシュとクライアントサイドのルーターキャッシュ {#data-cache-and-client-side-router-cache} +### Data Cacheとクライアント側のRouter cache {#data-cache-and-client-side-router-cache} -- データキャッシュとルーターキャッシュを即座に無効化するには[Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で[`revalidatePath`](#revalidatepath)または[`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag)を使用できます。 -- [Route Handler](/docs/app/building-your-application/routing/route-handlers)でデータキャッシュを再検証しても、Router Cacheは直ちには無効化されません。これらのRoute Handlerは特定のルートに結び付けられていないため、Router Cacheはハードリフレッシュまたは自動無効化期間が経過するまで以前のペイロードを提供し続けます。 +- [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations)で[`revalidatePath`](#revalidatepath)または[`revalidateTag`](#fetch-optionsnexttags-and-revalidatetag)を使用することでData CacheとRouter cacheをすぐに無効化できます。 +- [Route Handler](/docs/app/building-your-application/routing/route-handlers)でData Cacheを再検証しても、Router Cacheをすぐに無効化することはありません。Route Handlerは特定のルートに結び付いていません。これはハードリフレッシュまたは自動無効化期間が経過するまではRouter Cacheが以前のペイロードを提供し続けることを意味します。 ## API {#apis} -次の表は、さまざまなNext.js APIがキャッシングにどのような影響を与えるかの概要を示しています: +次の表は、さまざまなNext.jsのAPIがキャッシングにどのように影響を与えるかの概要です。 -| API | Router Cache | フルルートキャッシュ | Data Cache | React Cache | +| API | Router Cache | Full Route Cache | Data Cache | React Cache | | ----------------------------------------------------------------------- | -------------------------- | --------------------- | --------------------- | ----------- | | [``](#link) | Cache | | | | | [`router.prefetch`](#routerprefetch) | Cache | | | | @@ -400,139 +400,138 @@ Next.js 15以降、ページセグメントはデフォルトでオプトアウ ### `` {#link} -デフォルトでは、``コンポーネントはフルルートキャッシュからルートを自動的に事前取得し、Router CacheにReact Server Component Payloadを追加します。 +デフォルトで、``コンポーネントはFull Route Cacheからのルートを自動的にプリフェッチし、React Server Component PayloadをRouter Cacheに追加します。 -事前取得を無効にするには、`prefetch`プロパティを`false`に設定します。ただし、これはキャッシュを永続的にスキップすることはなく、ユーザーがルートを訪問したときにルートセグメントはクライアント側でキャッシュされます。 +プリフェッチを無効にするには、`prefetch`プロップを`false`に設定します。ただし、これによりキャッシュは恒久的にスキップされるわけではなく、ユーザーがルートを訪れるとクライアント側でルートセグメントがキャッシュされます。 -[``コンポーネント](/docs/app/api-reference/components/link)の詳細を学ぶ。 +[``コンポーネント](/docs/app/api-reference/components/link)について詳細を学びます。 ### `router.prefetch` {#router-prefetch} -`useRouter`フックの`prefetch`プロパティを使用して、ルートを手動で事前取得できます。これにより、Router CacheにReact Server Component Payloadを追加します。 +`使用Router`フックの`prefetch`オプションは、ルートを手動でプリフェッチするために使用できます。これにより、React Server Component PayloadがRouter Cacheに追加されます。 [`useRouter`フック](/docs/app/api-reference/functions/use-router)のAPIリファレンスを参照してください。 ### `router.refresh` {#router-refresh} -`useRouter`フックの`refresh`プロパティを使用して、ルートを手動で更新できます。これによりRouter Cacheが完全にクリアされ、現在のルートに対するサーバーへの新しいリクエストが行われます。`refresh`はデータキャッシュまたはフルルートキャッシュには影響を与えません。 +`使用Router`フックの`refresh`オプションを使用して、ルートを手動で更新できます。これにより、Router Cacheが完全にクリアされ、現在のルートのサーバーへの新しいリクエストが行われます。`refresh`はDataまたはFull Route Cacheに影響を与えません。 -描画結果はクライアント側で統合され、React状態やブラウザ状態が保持されます。 +レンダリングされた結果は、Reactとブラウザの状態を保持しながらクライアントで調和されます。 [`useRouter`フック](/docs/app/api-reference/functions/use-router)のAPIリファレンスを参照してください。 ### `fetch` {#fetch} -`fetch`から返されたデータは、自動的にデータキャッシュにキャッシュされます。 +`fetch`から返されるデータは、Data Cacheに自動的にキャッシュされ**ません**。 -`fetch`からの応答をキャッシュしたくない場合、以下のようにできます: +`fetch`のデフォルトのキャッシュ動作(例:`cache`オプションが指定されていない場合)は`cache`オプションを`no-store`に設定した場合と等しいです。 ```js let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' }) ``` -[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でその他のオプションを確認してください。 +[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でより多くのオプションをご覧ください。 ### `fetch options.cache` {#fetch-options-cache} -個々の`fetch`をキャッシュにオプトインする場合、`cache`オプションを`force-cache`に設定します: +個々の`fetch`を`force-cache`に設定してキャッシュにオプトインできます。 ```jsx // キャッシュにオプトイン fetch(`https://...`, { cache: 'force-cache' }) ``` -[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でその他のオプションを確認してください。 +[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でより多くのオプションをご覧ください。 ### `fetch options.next.revalidate` {#fetch-options-next-revalidate} -`fetch`の`next.revalidate`オプションを使用して、個々の`fetch`リクエストの再検証期間(秒単位)を設定することができます。これによりデータキャッシュが再検証され、結果としてフルルートキャッシュも再検証されます。新鮮なデータが取得され、コンポーネントがサーバー上で再レンダリングされます。 +個々の`fetch`リクエストの再検証期間(秒)を設定するために、`fetch`の`next.revalidate`オプションを使用できます。これによりData Cacheが再検証され、同時にFull Route Cacheも再検証されます。新鮮なデータがフェッチされ、サーバーでコンポーネントが再レンダリングされます。 ```jsx // 最大1時間後に再検証 fetch(`https://...`, { next: { revalidate: 3600 } }) ``` -[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でその他のオプションを確認してください。 +[`fetch` APIリファレンス](/docs/app/api-reference/functions/fetch)でより多くのオプションをご覧ください。 -### `fetch options.next.tags` and `revalidateTag` {#fetch-options-next-tags-and-revalidatetag} +### `fetch options.next.tags`と`revalidateTag` {#fetch-options-next-tags-and-revalidatetag} -Next.jsには、細かなデータキャッシングと再検証のためのキャッシュタグシステムがあります。 +Next.jsには、細粒度のデータキャッシュと再検証のためのキャッシュタグシステムがあります。 -1. `fetch`や[`unstable_cache`](/docs/app/api-reference/functions/unstable_cache)を使用するときに、キャッシュエントリを1つ以上のタグでタグ付けするオプションがあります。 -2. その後、タグに関連付けられたキャッシュエントリを削除するために`revalidateTag`を呼び出すことができます。 +1. `fetch`または[`unstable_cache`](/docs/app/api-reference/functions/unstable_cache)を使用する場合、キャッシュエントリに1つまたは複数のタグを設定するオプションがあります。 +2. 次に、`revalidateTag`を呼び出して、そのタグに関連付けられたキャッシュエントリを削除できます。 -たとえば、データを取得する際にタグを設定できます: +たとえば、データをフェッチする際にタグを設定できます。 ```jsx // データをタグでキャッシュ fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } }) ``` -次に、特定のタグを持つキャッシュエントリを削除して`revalidateTag`を呼び出します: +次に、タグを指定してキャッシュエントリを削除するには、`revalidateTag`を呼び出します。 ```jsx -// 特定のタグを持つエントリを再検証 +// 特定のタグを含むエントリを再検証 revalidateTag('a') ``` -使用目的によって、`revalidateTag`を次の場所で使用できます: +`revalidateTag`を使用できる場所は、目的に応じて異なります。 -1. [Route Handlers](/docs/app/building-your-application/routing/route-handlers) - サードパーティーイベント(例:Webhook)の応答としてデータを再検証する。 - -2. [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) - ユーザーアクション(例:フォーム送信)後にデータを再検証する。 この場合、関連するルートのRouter Cacheは無効化されます。 +1. [Route Handlers](/docs/app/building-your-application/routing/route-handlers) - サードパーティイベントに応答してデータを再検証します(例:webhook)。Router Cacheはすぐに無効化されません。これは、Router Handlerが特定のルートに結びついていないためです。 +2. [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) - ユーザーアクション後にデータを再検証します(例:フォーム送信)。これにより、関連するルートのRouter Cacheが無効化されます。 ### `revalidatePath` {#revalidatepath} -`revalidatePath`を使って、特定のパス以下のルートセグメントを再レンダリングしつつデータを手動で再検証することが可能です。このメソッドを呼び出すことでデータキャッシュが再検証され、その結果フルルートキャッシュも無効化されます。 +`revalidatePath`を使用して、特定のパス以下のルートセグメントを一度に再検証して再レンダリングできます。`revalidatePath`メソッドを呼び出すと、Data Cacheが再検証され、その結果、Full Route Cacheが無効化されます。 ```jsx revalidatePath('/') ``` -使用目的によって、`revalidatePath`を次の場所で使用できます: +`revalidatePath`を使用できる場所は、目的に応じて異なります。 -1. [Route Handlers](/docs/app/building-your-application/routing/route-handlers) - サードパーティーイベント(例:Webhook)の応答としてデータを再検証する。 -2. [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) - ユーザーインタラクション(例:フォーム送信、ボタンのクリック)後にデータを再検証する。 +1. [Route Handlers](/docs/app/building-your-application/routing/route-handlers) - サードパーティイベントに応答してデータを再検証します(例:webhook)。 +2. [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) - ユーザーインタラクション後にデータを再検証します(例:フォーム送信、ボタンをクリック)。 -[`revalidatePath` APIリファレンス](/docs/app/api-reference/functions/revalidatePath)で詳細を確認してください。 +[`revalidatePath` APIリファレンス](/docs/app/api-reference/functions/revalidatePath)で詳細をご覧ください。 -> **`revalidatePath`** と **`router.refresh`**: +> **`revalidatePath`** vs. **`router.refresh`**: > -> `router.refresh`を呼び出すと、Router Cacheがクリアされ、サーバー上でルートセグメントが再レンダリングされますが、データキャッシュやフルルートキャッシュは無効化されません。 +> `router.refresh`を呼び出すことで、Router cacheをクリアし、Data CacheやFull Route Cacheを無効化せずにサーバーでルートセグメントを再レンダリングできます。 > -> `revalidatePath`はデータキャッシュとフルルートキャッシュをクリアしますが、`router.refresh()`はデータキャッシュとフルルートキャッシュを変更しないという違いがあります。 +> 違いは、`revalidatePath`がData CacheおよびFull Route Cacheを削除するのに対し、`router.refresh()`はData CacheおよびFull Route Cacheを変更しないという点です。これはクライアントサイドのAPIです。 -### 動的API {#dynamic-apis} +### Dynamic APIs {#dynamic-apis} -`cookies`や`headers`のような動的API、およびPages内の`searchParams`プロップは実行時のインカミングリクエスト情報に依存します。これらを使用すると、ルートがフルルートキャッシュからオプトアウトし、つまり、ルートが動的にレンダリングされることになります。 +`cookies`や`headers`、Pages内の`searchParams` propなどの動的APIは、ランタイムの受信リクエスト情報に依存しています。それらを使用すると、Full Route Cacheからオプトアウトされます。つまり、ルートは動的にレンダリングされます。 #### `cookies` {#cookies} -Server Action内で`cookies.set`または`cookies.delete`を使用すると、それを使用するルートが古くならないように、Router Cacheを無効にします(例:認証の変更を反映するため)。 +Server Action内で`cookies.set`または`cookies.delete`を使用すると、Router Cacheを無効化します。これにより、cookiesを使用するルートが古くならないようにします(例:認証の反映)。 [`cookies`](/docs/app/api-reference/functions/cookies) APIリファレンスを参照してください。 -### セグメント設定オプション {#segment-config-options} +### Segment Config Options {#segment-config-options} -ルートセグメント設定オプションは、`fetch` APIを使用できない場合(例:データベースクライアントやサードパーティライブラリ)またはデフォルトを上書きする場合に、ルートセグメントの設定をオーバーライドするために使用できます。 +Route Segment Configオプションは、route segmentのデフォルトをオーバーライドしたり、`fetch` APIを使用できない場合(例: データベースクライアントまたはサードパーティライブラリ)に使用できます。 -次のルートセグメント設定オプションはフルルートキャッシュをオプトアウトします: +次のRoute Segment Configオプションは、Full Route Cacheからオプトアウトさせます。 - `const dynamic = 'force-dynamic'` -この設定オプションは、すべてのフェッチをデータキャッシュからオプトアウトします(すなわち`no-store`): +この設定オプションは、Data Cacheからすべてのフェッチをオプトアウト(例:`no-store`)します。 - `const fetchCache = 'default-no-store'` -[`fetchCache`](/docs/app/api-reference/file-conventions/route-segment-config#fetchcache)でより高度なオプションを確認してください。 +到達可能なより高度なオプションについては[`fetchCache`](/docs/app/api-reference/file-conventions/route-segment-config#fetchcache)をご覧ください。 -[ルートセグメント設定](/docs/app/api-reference/file-conventions/route-segment-config)のドキュメントで詳細なオプションを確認してください。 +より多くのオプションについては、[Route Segment Config](/docs/app/api-reference/file-conventions/route-segment-config)のドキュメントを参照してください。 ### `generateStaticParams` {#generatestaticparams} -[動的セグメント](/docs/app/building-your-application/routing/dynamic-routes)(例:`app/blog/[slug]/page.js`)について、`generateStaticParams`によって提供されるパスはビルドタイムにフルルートキャッシュにキャッシュされます。リクエスト時にNext.jsはビルドタイムに知られていなかったパスを初めて訪問した際にもキャッシュします。 +[動的セグメント](/docs/app/building-your-application/routing/dynamic-routes)(例:`app/blog/[slug]/page.js`)の場合、`generateStaticParams`によって提供されるパスはビルド時にFull Route Cacheにキャッシュされます。またリクエスト時に、ビルド時に既知でなかったパスも初回アクセス時にキャッシュされます。 -ビルドタイムにすべてのパスを静的にレンダリングするには、`generateStaticParams`にパスの完全なリストを提供します: +すべてのパスをビルド時に静的にレンダリングするには、`generateStaticParams`にフルパスリストを指定します。 ```jsx title="app/blog/[slug]/page.js" export async function generateStaticParams() { @@ -544,20 +543,20 @@ export async function generateStaticParams() { } ``` -ビルドタイムに一部のパスを静的にレンダリングし、残りは実行時に初めて訪問したときにレンダリングするには、部分的なパスのリストを返します: +ビルド時にパスのサブセットと、残りを実行時に初回アクセス時に静的にレンダリングするには、部分的なパスリストを返します。 ```jsx title="app/blog/[slug]/page.js" export async function generateStaticParams() { const posts = await fetch('https://.../posts').then((res) => res.json()) - // ビルドタイムに最初の10投稿をレンダリングする + // 最初の10個の投稿をビルド時にレンダリングします return posts.slice(0, 10).map((post) => ({ slug: post.slug, })) } ``` -訪問時に初めてすべてのパスを静的にレンダリングするには、空の配列を返します(ビルドタイムにはパスはレンダリングされませnん)または[`export const dynamic = 'force-static'`](/docs/app/api-reference/file-conventions/route-segment-config#dynamic)を利用します: +最初の訪問時にすべてのパスを静的にレンダリングするには、空の配列(ビルド時にパスはレンダリングされません)を返すか、[`export const dynamic = 'force-static'`](/docs/app/api-reference/file-conventions/route-segment-config#dynamic)を利用します。 ```jsx title="app/blog/[slug]/page.js" export async function generateStaticParams() { @@ -565,19 +564,19 @@ export async function generateStaticParams() { } ``` -> **Good to know:** `generateStaticParams`から配列を返す必要があります。たとえそれが空でもそうです。さもなければ、ルートは動的にレンダリングされます。 +> **知っておくと良いこと**: `generateStaticParams`からは、たとえ空でも配列を返さなければなりません。そうしないと、ルートは動的にレンダリングされます。 ```jsx title="app/changelog/[slug]/page.js" export const dynamic = 'force-static' ``` -リクエスト時のキャッシングを無効にするには、ルートセグメントに`export const dynamicParams = false`オプションを追加します。この設定オプションが使用された場合、`generateStaticParams`によって提供されたパスのみが提供され、その他のルートは404になったり(一致した場合には[catch-all routes](/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments))になります。 +リクエスト時にキャッシュを無効にするには、ルートセグメントに`export const dynamicParams = false`オプションを追加します。この設定オプションが使用されている場合、`generateStaticParams`によって提供されるパスのみが提供され、他のルートは404になったり一致する可能性があります([catch-all routes](/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments)の場合)。 -### React `cache`関数 {#react-cache-function} +### React `cache` 関数 {#react-cache-function} -Reactの`cache`関数を使用すると、関数の戻り値をメモ化でき、同じ関数を複数回呼び出しながらも、一度だけ実行することができます。 +Reactの`cache`関数を使用すると、関数の戻り値をメモ化できます。これにより、同じ関数を複数回呼び出しつつも、1度しか実行されません。 -`fetch`リクエストは自動的にメモ化されるため、React `cache`でラップする必要はありませんが、`fetch` APIが適さない場合にデータリクエストを手動でメモ化するために`cache`を使用することができます。例えば、一部のデータベースクライアント、CMSクライアント、またはGraphQLクライアントなどの場合。 +`fetch`リクエストは自動的にメモ化されるため、Reactの`cache`でラップする必要はありません。ただし、`fetch` APIが適していないユースケースの場合、たとえば一部のデータベースクライアント、CMSクライアント、またはGraphQLクライントの場合にデータリクエストを手動でメモ化するために`cache`を使用できます。 diff --git a/docs/01-app/02-building-your-application/06-optimizing/02-videos.mdx b/docs/01-app/02-building-your-application/06-optimizing/02-videos.mdx index 1443435..cfec573 100644 --- a/docs/01-app/02-building-your-application/06-optimizing/02-videos.mdx +++ b/docs/01-app/02-building-your-application/06-optimizing/02-videos.mdx @@ -1,18 +1,18 @@ --- -title: 'ビデオ最適化' -nav_title: 'ビデオ' -description: 'Next.jsアプリケーションでのビデオ最適化のための推奨事項とベストプラクティス' +title: 'Video Optimization' +nav_title: 'Videos' +description: 'Next.jsアプリケーションの動画最適化の推奨事項とベストプラクティス。' --- -このページでは、Next.jsアプリケーションでビデオをどのように使用するかを説明し、パフォーマンスに影響を与えずにビデオファイルを保存して表示する方法を示します。 +このページでは、Next.jsアプリケーションで動画を使用する方法を説明し、パフォーマンスに影響を与えずに動画ファイルを保存し表示する方法を示します。 -## `