From 58ea19390eca8ea64d7d1dd8520451e7c75c8e85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 03:06:57 +0000 Subject: [PATCH] sync docs@c824a7a --- .github/ISSUE_TEMPLATE/bug_report.md | 18 +- .github/ISSUE_TEMPLATE/issue_template.md | 1 - .../01-getting-started/01-installation.mdx | 147 ++-- .../02-project-structure.mdx | 296 ++++---- .../03-layouts-and-pages.mdx | 305 ++++++++ .../04-images-and-fonts.mdx | 433 ++++++++++++ .../01-getting-started/05-css-and-styling.mdx | 640 +++++++++++++++++ .../06-data-fetching-and-streaming.mdx | 413 +++++++++++ docs/01-app/01-getting-started/index.mdx | 9 +- .../01-routing/04-linking-and-navigating.mdx | 128 ++-- .../01-routing/05-error-handling.mdx | 108 ++- .../01-routing/07-redirecting.mdx | 258 +++---- .../01-routing/15-internationalization.mdx | 62 +- .../02-data-fetching/01-fetching.mdx | 242 ++++--- .../03-server-actions-and-mutations.mdx | 330 +++++---- .../04-incremental-static-regeneration.mdx | 244 +++---- .../03-rendering/01-server-components.mdx | 114 +-- .../03-rendering/03-composition-patterns.mdx | 210 +++--- .../04-caching/index.mdx | 393 +++++------ .../05-styling/01-css.mdx | 110 +-- .../06-optimizing/02-videos.mdx | 191 +++-- .../07-configuring/05-mdx.mdx | 240 ++++--- .../07-configuring/10-custom-server.mdx | 65 +- .../07-configuring/16-debugging.mdx | 102 +-- .../16-progressive-web-apps.mdx | 237 ++++--- .../09-authentication/index.mdx | 667 +++++++++--------- .../10-deploying/index.mdx | 250 ++++--- .../11-upgrading/01-codemods.mdx | 133 ++-- .../11-upgrading/02-canary.mdx | 38 + .../11-upgrading/03-version-14.mdx | 36 - .../{02-version-15.mdx => 03-version-15.mdx} | 210 +++--- .../11-upgrading/04-version-14.mdx | 36 + ...ration.mdx => 05-app-router-migration.mdx} | 0 ...t-app.mdx => 06-from-create-react-app.mdx} | 0 .../{06-from-vite.mdx => 07-from-vite.mdx} | 0 .../03-api-reference/02-components/image.mdx | 467 ++++++------ .../03-api-reference/02-components/link.mdx | 276 ++++---- .../01-metadata/sitemap.mdx | 72 +- .../03-file-conventions/default.mdx | 28 +- .../03-file-conventions/forbidden.mdx | 59 ++ .../03-file-conventions/layout.mdx | 90 +-- .../03-file-conventions/not-found.mdx | 24 +- .../03-file-conventions/page.mdx | 48 +- .../03-file-conventions/unauthorized.mdx | 141 ++++ .../03-api-reference/04-functions/after.mdx | 137 ++++ .../04-functions/cacheLife.mdx | 112 +-- .../04-functions/connection.mdx | 27 +- .../03-api-reference/04-functions/cookies.mdx | 114 +-- .../04-functions/draft-mode.mdx | 50 +- .../04-functions/expirePath.mdx | 144 ---- .../04-functions/expireTag.mdx | 102 --- .../03-api-reference/04-functions/fetch.mdx | 45 +- .../04-functions/forbidden.mdx | 208 ++++++ .../04-functions/generate-sitemaps.mdx | 33 +- .../04-functions/generate-static-params.mdx | 132 ++-- .../03-api-reference/04-functions/headers.mdx | 40 +- .../04-functions/revalidatePath.mdx | 58 +- .../04-functions/revalidateTag.mdx | 36 +- .../04-functions/unauthorized.mdx | 288 ++++++++ .../04-functions/unstable_after.mdx | 72 -- .../04-functions/unstable_expirePath.mdx | 145 ++++ .../04-functions/unstable_expireTag.mdx | 103 +++ .../04-functions/unstable_noStore.mdx | 19 +- .../01-next-config-js/authInterrupts.mdx | 44 ++ .../01-next-config-js/cssChunking.mdx | 19 +- .../05-config/01-next-config-js/inlineCss.mdx | 77 ++ .../01-next-config-js/reactCompiler.mdx | 47 +- .../01-next-config-js/staleTimes.mdx | 34 +- .../05-config/01-next-config-js/turbo.mdx | 74 +- .../05-config/02-typescript.mdx | 145 ++-- .../03-api-reference/05-config/03-eslint.mdx | 290 +++++--- docs/01-app/03-api-reference/06-cli/next.mdx | 222 +++--- docs/01-app/03-api-reference/07-edge.mdx | 258 +++---- docs/01-app/03-api-reference/08-turbopack.mdx | 85 +++ docs/03-architecture/nextjs-compiler.mdx | 188 +++-- docs/03-architecture/turbopack.mdx | 81 --- kj-diff.json | 80 ++- next.js | 2 +- static/img/docs/dark/app-getting-started.avif | Bin 3912 -> 4311 bytes static/img/docs/dark/blog-nested-route.avif | Bin 0 -> 12788 bytes .../img/docs/dark/blog-post-nested-route.avif | Bin 0 -> 18291 bytes static/img/docs/dark/caching-overview.avif | Bin 23812 -> 24340 bytes .../docs/dark/copy-devtool-url-example.avif | Bin 33762 -> 34548 bytes static/img/docs/dark/data-cache.avif | Bin 16454 -> 16737 bytes .../dark/deduplicated-fetch-requests.avif | Bin 28593 -> 32073 bytes static/img/docs/dark/full-route-cache.avif | Bin 11412 -> 11722 bytes static/img/docs/dark/layout-special-file.avif | Bin 5940 -> 8105 bytes static/img/docs/dark/loading-file.avif | Bin 0 -> 10116 bytes static/img/docs/dark/loading-overview.avif | Bin 15388 -> 14564 bytes static/img/docs/dark/loading-ui.avif | Bin 8980 -> 8347 bytes .../nested-error-component-hierarchy.avif | Bin 17830 -> 18270 bytes static/img/docs/dark/nested-layouts.avif | Bin 0 -> 19996 bytes .../img/docs/dark/on-demand-revalidation.avif | Bin 15768 -> 15852 bytes static/img/docs/dark/page-special-file.avif | Bin 5822 -> 6788 bytes .../project-organization-app-root-split.avif | Bin 8271 -> 9527 bytes .../dark/project-organization-app-root.avif | Bin 6865 -> 8014 bytes .../dark/project-organization-colocation.avif | Bin 18544 -> 20140 bytes .../project-organization-not-routable.avif | Bin 8398 -> 8864 bytes .../project-organization-private-folders.avif | Bin 10362 -> 11640 bytes .../project-organization-project-root.avif | Bin 6783 -> 7908 bytes .../project-organization-route-groups.avif | Bin 10341 -> 11357 bytes .../project-organization-src-directory.avif | Bin 7557 -> 8137 bytes static/img/docs/dark/public-folder.avif | Bin 0 -> 5323 bytes static/img/docs/dark/request-memoization.avif | Bin 12559 -> 12786 bytes .../docs/dark/shared-dashboard-layout.avif | Bin 6620 -> 7295 bytes .../docs/dark/static-and-dynamic-routes.avif | Bin 24551 -> 25149 bytes .../docs/dark/time-based-revalidation.avif | Bin 21752 -> 22597 bytes .../img/docs/light/app-getting-started.avif | Bin 3452 -> 3708 bytes static/img/docs/light/blog-nested-route.avif | Bin 0 -> 11063 bytes .../docs/light/blog-post-nested-route.avif | Bin 0 -> 14700 bytes static/img/docs/light/caching-overview.avif | Bin 19757 -> 20690 bytes .../light/deduplicated-fetch-requests.avif | Bin 16624 -> 18758 bytes static/img/docs/light/full-route-cache.avif | Bin 11347 -> 11644 bytes .../img/docs/light/layout-special-file.avif | Bin 4662 -> 7271 bytes static/img/docs/light/loading-file.avif | Bin 0 -> 8592 bytes static/img/docs/light/loading-overview.avif | Bin 14630 -> 14051 bytes static/img/docs/light/nested-layouts.avif | Bin 0 -> 16955 bytes .../docs/light/on-demand-revalidation.avif | Bin 11853 -> 12145 bytes static/img/docs/light/page-special-file.avif | Bin 5147 -> 6081 bytes static/img/docs/light/partial-rendering.avif | Bin 12277 -> 13514 bytes .../project-organization-app-root-split.avif | Bin 6179 -> 7116 bytes .../light/project-organization-app-root.avif | Bin 5629 -> 6300 bytes .../light/project-organization-routable.avif | Bin 7961 -> 8779 bytes static/img/docs/light/public-folder.avif | Bin 0 -> 4402 bytes .../img/docs/light/request-memoization.avif | Bin 11807 -> 12190 bytes .../docs/light/shared-dashboard-layout.avif | Bin 5039 -> 5706 bytes .../docs/light/static-and-dynamic-routes.avif | Bin 24272 -> 24442 bytes .../docs/light/time-based-revalidation.avif | Bin 15637 -> 16513 bytes 128 files changed, 7188 insertions(+), 4194 deletions(-) create mode 100644 docs/01-app/01-getting-started/03-layouts-and-pages.mdx create mode 100644 docs/01-app/01-getting-started/04-images-and-fonts.mdx create mode 100644 docs/01-app/01-getting-started/05-css-and-styling.mdx create mode 100644 docs/01-app/01-getting-started/06-data-fetching-and-streaming.mdx create mode 100644 docs/01-app/02-building-your-application/11-upgrading/02-canary.mdx delete mode 100644 docs/01-app/02-building-your-application/11-upgrading/03-version-14.mdx rename docs/01-app/02-building-your-application/11-upgrading/{02-version-15.mdx => 03-version-15.mdx} (55%) create mode 100644 docs/01-app/02-building-your-application/11-upgrading/04-version-14.mdx rename docs/01-app/02-building-your-application/11-upgrading/{04-app-router-migration.mdx => 05-app-router-migration.mdx} (100%) rename docs/01-app/02-building-your-application/11-upgrading/{05-from-create-react-app.mdx => 06-from-create-react-app.mdx} (100%) rename docs/01-app/02-building-your-application/11-upgrading/{06-from-vite.mdx => 07-from-vite.mdx} (100%) create mode 100644 docs/01-app/03-api-reference/03-file-conventions/forbidden.mdx create mode 100644 docs/01-app/03-api-reference/03-file-conventions/unauthorized.mdx create mode 100644 docs/01-app/03-api-reference/04-functions/after.mdx delete mode 100644 docs/01-app/03-api-reference/04-functions/expirePath.mdx delete mode 100644 docs/01-app/03-api-reference/04-functions/expireTag.mdx create mode 100644 docs/01-app/03-api-reference/04-functions/forbidden.mdx create mode 100644 docs/01-app/03-api-reference/04-functions/unauthorized.mdx delete mode 100644 docs/01-app/03-api-reference/04-functions/unstable_after.mdx create mode 100644 docs/01-app/03-api-reference/04-functions/unstable_expirePath.mdx create mode 100644 docs/01-app/03-api-reference/04-functions/unstable_expireTag.mdx create mode 100644 docs/01-app/03-api-reference/05-config/01-next-config-js/authInterrupts.mdx create mode 100644 docs/01-app/03-api-reference/05-config/01-next-config-js/inlineCss.mdx create mode 100644 docs/01-app/03-api-reference/08-turbopack.mdx delete mode 100644 docs/03-architecture/turbopack.mdx create mode 100644 static/img/docs/dark/blog-nested-route.avif create mode 100644 static/img/docs/dark/blog-post-nested-route.avif create mode 100644 static/img/docs/dark/loading-file.avif create mode 100644 static/img/docs/dark/nested-layouts.avif create mode 100644 static/img/docs/dark/public-folder.avif create mode 100644 static/img/docs/light/blog-nested-route.avif create mode 100644 static/img/docs/light/blog-post-nested-route.avif create mode 100644 static/img/docs/light/loading-file.avif create mode 100644 static/img/docs/light/nested-layouts.avif create mode 100644 static/img/docs/light/public-folder.avif diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea78..b5c68e55 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 4be775cb..e04efde8 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/01-installation.mdx b/docs/01-app/01-getting-started/01-installation.mdx index 0abfd7ba..21419c99 100644 --- a/docs/01-app/01-getting-started/01-installation.mdx +++ b/docs/01-app/01-getting-started/01-installation.mdx @@ -1,27 +1,27 @@ --- -title: 'Next.jsプロジェクトをセットアップする方法' -sidebar_label: 'インストール' -description: '`create-next-app`を使用して新しいNext.jsアプリケーションを作成し、TypeScript、ESLint、モジュールパスエイリアスを設定する方法を学びます。' +title: '新しい Next.js プロジェクトをセットアップする方法' +nav_title: 'インストール' +description: '`create-next-app` CLIを使用して新しい Next.js アプリケーションを作成し、TypeScript、ESLint、モジュールパスエイリアスをセットアップします。' --- -{/* このドキュメントの内容はapp routerとpages routerに共有されています。Pages Routerに特化したコンテンツを追加するために`コンテンツ`コンポーネントを使用することができます。共有されたコンテンツはコンポーネントでラップしないでください。 */} +{/* このドキュメントの内容は app router と pages router の間で共有されています。Pages Router に特有のコンテンツを追加するには `Content` コンポーネントを使用できます。共有コンテンツはコンポーネントでラップすべきではありません。 */} ## システム要件 {#system-requirements} -- [Node.js 18.18](https://nodejs.org/) 以上。 -- macOS、Windows(WSLを含む)、Linuxがサポートされています。 +- [Node.js 18.18](https://nodejs.org/) 以上 +- macOS、Windows(WSLを含む)、およびLinuxがサポートされています ## 自動インストール {#automatic-installation} -私たちは、すべてを自動的に設定する[`create-next-app`](/docs/app/api-reference/cli/create-next-app)を使用して新しいNext.jsアプリを始めることをお勧めします。プロジェクトを作成するには、以下のコマンドを実行してください: +[`create-next-app`](/docs/app/api-reference/cli/create-next-app) を使用して新しい Next.js アプリを始めることをお勧めします。これにより、すべてが自動的にセットアップされます。プロジェクトを作成するには、以下を実行します: -```bash title="ターミナル" +```bash title="Terminal" npx create-next-app@latest ``` -インストール中に、次のプロンプトが表示されます: +インストール時に、次のプロンプトが表示されます: -```txt title="ターミナル" +```txt title="Terminal" What is your project named? my-app Would you like to use TypeScript? No / Yes Would you like to use ESLint? No / Yes @@ -33,17 +33,17 @@ Would you like to customize the import alias (`@/*` by default)? No / Yes What import alias would you like configured? @/* ``` -プロンプトが完了すると、[`create-next-app`](/docs/app/api-reference/cli/create-next-app)はあなたのプロジェクト名でフォルダを作成し、必要な依存関係をインストールします。 +プロンプトに答えた後、[`create-next-app`](/docs/app/api-reference/cli/create-next-app) はプロジェクト名のフォルダを作成し、必要な依存関係をインストールします。 ## 手動インストール {#manual-installation} -手動で新しいNext.jsアプリを作成するには、必要なパッケージをインストールします: +新しい Next.js アプリを手動で作成するには、必要なパッケージをインストールします: -```bash title="ターミナル" +```bash title="Terminal" npm install next@latest react@latest react-dom@latest ``` -`package.json`ファイルを開き、以下の`scripts`を追加してください: +`package.json` ファイルを開き、次の `scripts` を追加します: ```json title="package.json" { @@ -56,30 +56,30 @@ npm install next@latest react@latest react-dom@latest } ``` -これらのスクリプトは、アプリケーションの開発のさまざまな段階を参照しています: +これらのスクリプトは、アプリケーション開発の異なる段階を指します: -- `dev`: [`next dev`](/docs/app/api-reference/cli/next#next-dev-options)を実行して、Next.jsを開発モードで開始します -- `build`: [`next build`](/docs/app/api-reference/cli/next#next-build-options)を実行して、アプリケーションを本番環境用にビルドします -- `start`: [`next start`](/docs/app/api-reference/cli/next#next-start-options)を実行して、Next.jsの本番サーバーを開始します -- `lint`: [`next lint`](/docs/app/api-reference/cli/next#next-lint-options)を実行して、Next.jsの組み込みESLint構成を設定します +- `dev`: [`next dev`](/docs/app/api-reference/cli/next#next-dev-options) を実行して、Next.js を開発モードで開始します +- `build`: [`next build`](/docs/app/api-reference/cli/next#next-build-options) を実行して、本番での使用のためにアプリケーションをビルドします +- `start`: [`next start`](/docs/app/api-reference/cli/next#next-start-options) を実行して、Next.js の本番サーバーを開始します +- `lint`: [`next lint`](/docs/app/api-reference/cli/next#next-lint-options) を実行して、Next.js の組み込みESLint設定をセットアップします -### `app`ディレクトリを作成する {#create-the-app-directory} +### `app` ディレクトリを作成する {#create-the-app-directory} -Next.jsはファイルシステムルーティングを使用しており、アプリケーション内のルートはファイルの構造によって決まります。 +Next.js はファイルシステムルーティングを使用しており、アプリケーション内のルートはファイルの構造によって決まります。 -`app`フォルダを作成し、次に`layout.tsx`と`page.tsx`ファイルを追加します。これらは、ユーザーがアプリケーションのroot(`/`)にアクセスしたときに表示されます。 +`app` フォルダを作成し、次に `layout.tsx` と `page.tsx` ファイルを追加します。これらは、ユーザーがアプリケーションの root (`/`) を訪問したときにレンダリングされます。 Appフォルダ構成 -[Root レイアウト](/docs/app/building-your-application/routing/layouts-and-templates#root-layout-required)を`app/layout.tsx`内に作成し、必要な``と``タグを含めます: +[Root レイアウト](/docs/app/building-your-application/routing/layouts-and-templates#root-layout-required) を `app/layout.tsx` 内に `` および `` タグを含めて作成します: @@ -91,7 +91,7 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - + {children} ) @@ -104,7 +104,7 @@ export default function RootLayout({ ```jsx title="app/layout.js" switcher export default function RootLayout({ children }) { return ( - + {children} ) @@ -114,7 +114,7 @@ export default function RootLayout({ children }) { -最後に、初期コンテンツのあるホームページ`app/page.tsx`を作成します: +最後に、初期コンテンツを含むホームページ `app/page.tsx` を作成します: @@ -139,18 +139,18 @@ export default function Page() { > **Good to know**: > -> - `layout.tsx`を作成し忘れた場合、`next dev`で開発サーバーを実行すると、Next.jsが自動的にこのファイルを作成します -> - プロジェクトのrootに[`src`ディレクトリ](/docs/app/building-your-application/configuring/src-directory)を使用して、アプリケーションのコードを設定ファイルから分離することができます +> - `layout.tsx` の作成を忘れると、Next.js は `next dev` で開発サーバーを実行するときに自動的にこのファイルを作成します。 +> - プロジェクトの root にある[`src` ディレクトリ](/docs/app/building-your-application/configuring/src-directory)を使用して、アプリケーションのコードを設定ファイルから分離することができます。 -### `pages`ディレクトリを作成する {#create-the-pages-directory} +### `pages` ディレクトリを作成する {#create-the-pages-directory} -Next.jsはファイルシステムルーティングを使用しており、アプリケーション内のルートはファイルの構造によって決まります。 +Next.js はファイルシステムルーティングを使用しており、アプリケーション内のルートはファイルの構造によって決まります。 -プロジェクトのrootに`pages`ディレクトリを作成します。それから、`pages`フォルダ内に`index.tsx`ファイルを追加します。これがホームページ(`/`)になります: +プロジェクトの root に `pages` ディレクトリを作成します。次に、`pages` フォルダ内に `index.tsx` ファイルを追加します。これがホームページ (`/`) になります: @@ -173,7 +173,7 @@ export default function Page() { -次に、`pages/`内に`_app.tsx`ファイルを追加して、グローバルレイアウトを定義します。 [カスタムAppファイル](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-app)についてさらに学びます。 +次に、 `pages/` 内に `_app.tsx` ファイルを追加して、グローバルレイアウトを定義します。詳細は [カスタム App ファイル](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-app) を参照してください。 @@ -198,7 +198,7 @@ export default function App({ Component, pageProps }) { -最後に、`pages/`内に`_document.tsx`ファイルを追加して、サーバーからの初期応答を制御します。[カスタムDocumentファイル](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-document)についてさらに学びます。 +最後に、`pages/` 内に `_document.tsx` ファイルを追加して、サーバーからの初期応答を制御します。詳細は [カスタム Document ファイル](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-document) を参照してください。 @@ -243,57 +243,52 @@ export default function Document() { -### `public`フォルダを作成する(オプション) {#create-the-public-folder-optional} +### `public` フォルダを作成する(オプション) {#create-the-public-folder-optional} -プロジェクトのrootに[`public`フォルダ](/docs/app/building-your-application/optimizing/static-assets)を作成して、画像、フォントなどの静的アセットを保存することができます。`public`内のファイルは、それ以降コード内で基準URL(`/`)から参照することができます。 +プロジェクトの root に [`public` フォルダ](/docs/app/building-your-application/optimizing/static-assets) を作成して、画像やフォントなどの静的アセットを保存することができます。`public` 内のファイルは、ベースURL (`/`) から始まるコードで参照できます。 ## 開発サーバーを実行する {#run-the-development-server} -1. `npm run dev`を実行して、開発サーバーを開始します。 -2. `http://localhost:3000`にアクセスして、アプリケーションを表示します。 -3. `app/page.tsx` `pages/index.tsx` ファイルを編集して保存し、ブラウザで更新された結果を確認します。 +1. `npm run dev` を実行して開発サーバーを開始します。 +2. `http://localhost:3000` にアクセスしてアプリケーションを表示します。3.`app/page.tsx` `pages/index.tsx` ファイルを編集して保存すると、ブラウザで更新された結果が表示されます。 -## TypeScriptを設定する {#set-up-typescript} +## TypeScript をセットアップする {#set-up-typescript} -> 最低限のTypeScriptバージョン: `v4.5.2` +> 最小 TypeScript バージョン: `v4.5.2` -Next.jsは、組み込みのTypeScriptサポートを備えています。プロジェクトにTypeScriptを追加するには、ファイルの形式を`.ts`または`.tsx`に変更します。`next dev`を実行すると、Next.jsが必要な依存関係を自動的にインストールし、推奨構成オプションを含む`tsconfig.json`ファイルを追加します。 - -> **Good to know**: -> -> - すでに`jsconfig.json`ファイルを持っている場合は、古い`jsconfig.json`から新しい`tsconfig.json`に`paths`コンパイラオプションをコピーし、古い`jsconfig.json`ファイルを削除します。 +Next.js は組み込みの TypeScript サポートを提供しています。プロジェクトに TypeScript を追加するには、ファイルを `.ts` / `.tsx` にリネームします。`next dev` を実行すると、Next.js は自動的に必要な依存関係をインストールし、推奨される設定オプションを持つ `tsconfig.json` ファイルを追加します。 -### IDEプラグイン {#ide-plugin} +### IDE プラグイン {#ide-plugin} -Next.jsには、カスタムTypeScriptプラグインと型チェッカーが含まれており、VSCodeおよび他のコードエディタで高度な型検査と自動補完を利用できます。 +Next.js にはカスタム TypeScript プラグインと型チェッカーが含まれており、VSCode や他のコードエディターが高度な型チェックや自動補完に使用することができます。 -VS Codeでこのプラグインを有効にするには、以下の手順に従ってください: +VS Code でプラグインを有効にするには: 1. コマンドパレットを開く(`Ctrl/⌘` + `Shift` + `P`) 2. 「TypeScript: Select TypeScript Version」を検索 3. 「Use Workspace Version」を選択 TypeScriptコマンドパレット -これでファイルを編集すると、カスタムプラグインが有効になります。`next build`を実行すると、カスタム型チェッカーが使用されます。 +ファイルを編集するときに、カスタムプラグインが有効になります。`next build` を実行すると、カスタムの型チェッカーが使用されます。 -[TypeScript構成](/docs/app/api-reference/config/next-config-js/typescript)ページでは、プロジェクトでTypeScriptを使用する方法についてさらに詳しく知ることができます。 +プロジェクトで TypeScript を使用する方法の詳細については、[TypeScript の設定](/docs/app/api-reference/config/next-config-js/typescript) ページを参照してください。 -## ESLintを設定する {#set-up-eslint} +## ESLintをセットアップする {#set-up-eslint} -Next.jsは組み込みのESLintを備えており、`create-next-app`で新しいプロジェクトを作成する際に必要なパッケージを自動的にインストールし、適切な設定を行います。 +Next.js には組み込みのESLintが含まれており、プロジェクトを `create-next-app` で作成するときに必要なパッケージを自動的にインストールし、適切な設定を行います。 -既存のプロジェクトにESLintを追加するには、`package.json`に`next lint`をスクリプトとして追加します: +既存のプロジェクトに ESLint を追加するには、`package.json` に `next lint` をスクリプトとして追加します: ```json title="package.json" { @@ -303,33 +298,33 @@ Next.jsは組み込みのESLintを備えており、`create-next-app`で新し } ``` -その後、`npm run lint`を実行すると、インストールおよび設定プロセスがガイドされます。 +次に、`npm run lint` を実行すると、インストールと設定のプロセスが案内されます。 -```bash title="ターミナル" +```bash title="Terminal" pnpm lint ``` -次のようなプロンプトが表示されます: +次のようなプロンプトが表示されます: -> ? How would you like to configure ESLint? +> ? ESLint をどのように設定しますか? > -> ❯ Strict (recommended) -> Base -> Cancel +> ❯ 厳格(推奨) +> 基本 +> キャンセル -- **Strict**: Next.jsの基本的なESLint構成と、より厳格なCore Web Vitalsルールセットを含みます。初めてESLintを設定する開発者には、この設定が推奨されます -- **Base**: Next.jsの基本的なESLint構成を含みます -- **Cancel**: どのESLint構成も含まれません。このオプションは独自のカスタムESLint構成を設定する予定がある場合にのみ選択してください +- **厳格**: Next.js の基本 ESLint 設定に加えて、より厳しい Core Web Vitals ルールセットが含まれます。これが初めて ESLint を設定する開発者のための推奨設定です。 +- **基本**: Next.js の基本 ESLint 設定が含まれます。 +- **キャンセル**: どの ESLint 設定も含まれません。このオプションは、独自のカスタム ESLint 設定を計画している場合にのみ選択します。 -2つの構成オプションのいずれかが選択されると、Next.jsは自動的に`eslint`と`eslint-config-next`をアプリケーションの依存関係としてインストールし、プロジェクトのrootに選択した構成を含む`.eslintrc.json`ファイルを作成します。 +どちらかの設定オプションを選択した場合、Next.js は自動的に `eslint` と `eslint-config-next` をアプリケーション内に依存関係としてインストールし、選択した設定を含む `.eslintrc.json` ファイルをプロジェクトの root に作成します。 -ESLintを実行してエラーを検出したい時はいつでも`next lint`を実行できます。ESLintが設定されると、毎回のビルド(`next build`)中にも自動的に実行されます。エラーはビルドを失敗させ、警告はビルドを失敗させません。 +ESLint でエラーを検出するたびに `next lint` を実行できます。ESLint の設定が終わると、ビルド(`next build`)時にも自動的に実行されます。エラーはビルドを失敗させ、警告は失敗させません。 -[ESLint Plugin](/docs/app/api-reference/config/next-config-js/eslint)ページでは、プロジェクトでESLintを設定する方法についてさらに詳しく知ることができます。 +プロジェクトで ESLint を設定する方法の詳細については、[ESLint プラグイン](/docs/app/api-reference/config/next-config-js/eslint) ページを参照してください。 -## 絶対インポートとモジュールパスエイリアスを設定する {#set-up-absolute-imports-and-module-path-aliases} +## 絶対インポートとモジュールパスエイリアスをセットアップする {#set-up-absolute-imports-and-module-path-aliases} -Next.jsは、`tsconfig.json`および`jsconfig.json`ファイルの`"paths"`および`"baseUrl"`オプションをサポートしています。これらのオプションを利用することで、プロジェクトディレクトリを絶対パスにエイリアスし、モジュールのインポートをより簡単にすることができます。例: +Next.js は `tsconfig.json` および `jsconfig.json` ファイルの `"paths"` と `"baseUrl"` オプションをサポートしています。これらのオプションを使用してプロジェクトディレクトリを絶対パスにエイリアスし、モジュールのインポートを簡単にします。たとえば: ```jsx // 変更前 @@ -339,9 +334,9 @@ import { Button } from '../../../components/button' import { Button } from '@/components/button' ``` -絶対インポートを設定するには、`tsconfig.json`または`jsconfig.json`ファイルに`baseUrl`構成オプションを追加します。例: +絶対インポートを設定するには、`tsconfig.json` または `jsconfig.json` ファイルに `baseUrl` 設定オプションを追加します。例: -```json title="tsconfig.jsonまたはjsconfig.json" +```json title="tsconfig.json または jsconfig.json" { "compilerOptions": { "baseUrl": "src/" @@ -349,11 +344,11 @@ import { Button } from '@/components/button' } ``` -また、`baseUrl`パスを構成するほかに、`"paths"`オプションを使ってモジュールパスを"エイリアス"することができます。 +`baseUrl` パスを設定するだけでなく、`"paths"` オプションを使用してモジュールパスを `"alias"` することもできます。 -例として、次の構成は`@/components/*`を`components/*`にマッピングします: +例えば、次の設定では、`@/components/*` を `components/*` にマップします: -```json title="tsconfig.jsonまたはjsconfig.json" +```json title="tsconfig.json または jsconfig.json" { "compilerOptions": { "baseUrl": "src/", @@ -365,7 +360,7 @@ import { Button } from '@/components/button' } ``` -各`"paths"`は`baseUrl`の場所に対して相対的です。例: +各 `"paths"` は `baseUrl` の場所からの相対パスです。例えば: diff --git a/docs/01-app/01-getting-started/02-project-structure.mdx b/docs/01-app/01-getting-started/02-project-structure.mdx index dc026be2..06d74005 100644 --- a/docs/01-app/01-getting-started/02-project-structure.mdx +++ b/docs/01-app/01-getting-started/02-project-structure.mdx @@ -1,121 +1,121 @@ --- -title: 'プロジェクト構造と組織化' -nav_title: 'プロジェクト構造' -description: 'Next.jsプロジェクトにおけるフォルダとファイルの規約、そしてプロジェクトの組織化方法について学びます' +title: 'プロジェクトの構造と組織化' +nav_title: 'Project Structure' +description: 'Next.jsにおけるフォルダーおよびファイルの規約の概要と、プロジェクトの組織化方法について。' --- -このページでは、Next.jsにおけるフォルダとファイルの規約、およびプロジェクトを組織化するためのヒントを紹介します。 +このページでは、Next.jsにおけるフォルダーおよびファイルの規約の概要と、プロジェクトの組織化に関するヒントを提供します。 -## フォルダとファイルの規約 {#folder-and-file-conventions} +## フォルダーとファイルの規約 {#folder-and-file-conventions} -### 最上位フォルダ {#top-level-folders} +### トップレベルのフォルダー {#top-level-folders} -最上位フォルダは、アプリケーションのコードと静的アセットを整理するために使用されます。 +トップレベルのフォルダーは、アプリケーションのコードと静的アセットを整理するために使用されます。 ルートセグメントからパスセグメントへの変換 -| | | -| --------------------------------------------------------------------------------- | ------------------------------------------ | -| [`app`](/docs/app/building-your-application/routing) | App Router | -| [`pages`](https://nextjs.org/docs/canary/pages/building-your-application/routing) | Pages Router | -| [`public`](/docs/app/building-your-application/optimizing/static-assets) | サーブされる静的アセット | -| [`src`](/docs/app/building-your-application/configuring/src-directory) | オプションのアプリケーションソースフォルダ | - -### 最上位ファイル {#top-level-files} - -最上位ファイルは、アプリケーションの設定、依存関係の管理、ミドルウェアの実行、モニタリングツールの統合、環境変数の定義に使用されます。 - -| | | -| ------------------------------------------------------------------------------------------- | ------------------------------------------------- | -| **Next.js** | | -| [`next.config.js`](/docs/app/api-reference/config/next-config-js) | Next.jsの設定ファイル | -| [`package.json`](/docs/app/getting-started/installation#manual-installation) | プロジェクトの依存関係とスクリプト | -| [`instrumentation.ts`](/docs/app/building-your-application/optimizing/instrumentation) | OpenTelemetryとインストゥルメンテーションファイル | -| [`middleware.ts`](/docs/app/building-your-application/routing/middleware) | Next.jsリクエストミドルウェア | -| [`.env`](/docs/app/building-your-application/configuring/environment-variables) | 環境変数 | -| [`.env.local`](/docs/app/building-your-application/configuring/environment-variables) | ローカル環境変数 | -| [`.env.production`](/docs/app/building-your-application/configuring/environment-variables) | 本番環境変数 | -| [`.env.development`](/docs/app/building-your-application/configuring/environment-variables) | 開発環境変数 | -| [`.eslintrc.json`](/docs/app/api-reference/config/eslint) | ESLintの設定ファイル | -| `.gitignore` | Gitで無視されるファイルとフォルダ | -| `next-env.d.ts` | Next.jsのTypeScript宣言ファイル | -| `tsconfig.json` | TypeScriptの設定ファイル | -| `jsconfig.json` | JavaScriptの設定ファイル | +| | | +| --------------------------------------------------------------------------------- | -------------------------------------------- | +| [`app`](/docs/app/building-your-application/routing) | App Router | +| [`pages`](https://nextjs.org/docs/canary/pages/building-your-application/routing) | Pages Router | +| [`public`](/docs/app/building-your-application/optimizing/static-assets) | 提供される静的アセット | +| [`src`](/docs/app/building-your-application/configuring/src-directory) | オプションのアプリケーションソースフォルダー | + +### トップレベルのファイル {#top-level-files} + +トップレベルのファイルは、アプリケーションの設定、依存関係の管理、ミドルウェアの実行、監視ツールの統合、環境変数の定義に使用されます。 + +| | | +| ------------------------------------------------------------------------------------------- | ---------------------------------------- | +| **Next.js** | | +| [`next.config.js`](/docs/app/api-reference/config/next-config-js) | Next.jsの設定ファイル | +| [`package.json`](/docs/app/getting-started/installation#manual-installation) | プロジェクトの依存関係とスクリプト | +| [`instrumentation.ts`](/docs/app/building-your-application/optimizing/instrumentation) | OpenTelemetryとInstrumentationのファイル | +| [`middleware.ts`](/docs/app/building-your-application/routing/middleware) | Next.jsリクエストミドルウェア | +| [`.env`](/docs/app/building-your-application/configuring/environment-variables) | 環境変数 | +| [`.env.local`](/docs/app/building-your-application/configuring/environment-variables) | ローカル環境変数 | +| [`.env.production`](/docs/app/building-your-application/configuring/environment-variables) | 本番環境変数 | +| [`.env.development`](/docs/app/building-your-application/configuring/environment-variables) | 開発環境変数 | +| [`.eslintrc.json`](/docs/app/api-reference/config/eslint) | ESLintの設定ファイル | +| `.gitignore` | Gitで無視するファイルやフォルダー | +| `next-env.d.ts` | Next.jsの型定義ファイル | +| `tsconfig.json` | TypeScriptの設定ファイル | +| `jsconfig.json` | JavaScriptの設定ファイル | ### ルーティングファイル {#routing-files} -| | | | -| ------------------------------------------------------------------------------- | ------------------- | ------------------------------------ | -| [`layout`](/docs/app/api-reference/file-conventions/layout) | `.js` `.jsx` `.tsx` | レイアウト | -| [`page`](/docs/app/api-reference/file-conventions/page) | `.js` `.jsx` `.tsx` | ページ | -| [`loading`](/docs/app/api-reference/file-conventions/loading) | `.js` `.jsx` `.tsx` | ローディングUI | -| [`not-found`](/docs/app/api-reference/file-conventions/not-found) | `.js` `.jsx` `.tsx` | 見つからないUI | -| [`error`](/docs/app/api-reference/file-conventions/error) | `.js` `.jsx` `.tsx` | エラーUI | -| [`global-error`](/docs/app/api-reference/file-conventions/error#global-errorjs) | `.js` `.jsx` `.tsx` | グローバルエラーUI | -| [`route`](/docs/app/api-reference/file-conventions/route) | `.js` `.ts` | APIエンドポイント | -| [`template`](/docs/app/api-reference/file-conventions/template) | `.js` `.jsx` `.tsx` | 再レンダリングされたレイアウト | -| [`default`](/docs/app/api-reference/file-conventions/default) | `.js` `.jsx` `.tsx` | パラレルルートのフェールバックページ | - -### ネストルート {#nested-routes} - -| | | -| ---------------------------------------------------------------------------- | ---------------------- | -| [`folder`](/docs/app/building-your-application/routing#route-segments) | ルートセグメント | -| [`folder/folder`](/docs/app/building-your-application/routing#nested-routes) | ネストルートセグメント | +| | | | +| ------------------------------------------------------------------------------- | ------------------- | -------------------------------- | +| [`layout`](/docs/app/api-reference/file-conventions/layout) | `.js` `.jsx` `.tsx` | レイアウト | +| [`page`](/docs/app/api-reference/file-conventions/page) | `.js` `.jsx` `.tsx` | ページ | +| [`loading`](/docs/app/api-reference/file-conventions/loading) | `.js` `.jsx` `.tsx` | ローディングUI | +| [`not-found`](/docs/app/api-reference/file-conventions/not-found) | `.js` `.jsx` `.tsx` | Not found UI | +| [`error`](/docs/app/api-reference/file-conventions/error) | `.js` `.jsx` `.tsx` | エラーUI | +| [`global-error`](/docs/app/api-reference/file-conventions/error#global-errorjs) | `.js` `.jsx` `.tsx` | グローバルエラーUI | +| [`route`](/docs/app/api-reference/file-conventions/route) | `.js` `.ts` | APIエンドポイント | +| [`template`](/docs/app/api-reference/file-conventions/template) | `.js` `.jsx` `.tsx` | 再レンダリングされたレイアウト | +| [`default`](/docs/app/api-reference/file-conventions/default) | `.js` `.jsx` `.tsx` | 平行ルートのフォールバックページ | + +### 入れ子になったルート {#nested-routes} + +| | | +| ---------------------------------------------------------------------------- | ------------------------------ | +| [`folder`](/docs/app/building-your-application/routing#route-segments) | ルートセグメント | +| [`folder/folder`](/docs/app/building-your-application/routing#nested-routes) | 入れ子になったルートセグメント | ### 動的ルート {#dynamic-routes} -| | | -| --------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -| [`[folder]`](/docs/app/building-your-application/routing/dynamic-routes#convention) | 動的ルートセグメント | -| [`[...folder]`](/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments) | キャッチオールルートセグメント | -| [`[[...folder]]`](/docs/app/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | オプションのキャッチオールルートセグメント | +| | | +| --------------------------------------------------------------------------------------------------------- | -------------------------------- | +| [`[folder]`](/docs/app/building-your-application/routing/dynamic-routes#convention) | 動的ルートセグメント | +| [`[...folder]`](/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments) | Catch-all route segment | +| [`[[...folder]]`](/docs/app/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | Optional catch-all route segment | -### ルートグループとプライベートフォルダ {#route-groups-and-private-folders} +### Route Groupsとプライベートフォルダー {#route-groups-and-private-folders} -| | | -| --------------------------------------------------------------------------------- | ---------------------------------------------------- | -| [`(folder)`](/docs/app/building-your-application/routing/route-groups#convention) | ルーティングに影響を与えずにルートをグループ化 | -| [`_folder`](#private-folders) | フォルダとすべての子セグメントをルーティングから除外 | +| | | +| --------------------------------------------------------------------------------- | -------------------------------------------------------------- | +| [`(folder)`](/docs/app/building-your-application/routing/route-groups#convention) | ルーティングに影響を与えずにルートをグループ化する | +| [`_folder`](#private-folders) | フォルダーとそのすべての子セグメントをルーティングから除外する | -### パラレルルートとインターセプタールート {#parallel-and-intercepted-routes} +### Parallel RoutesとIntercepted Routes {#parallel-and-intercepted-routes} -| | | -| ---------------------------------------------------------------------------------------------- | -------------------------- | -| [`@folder`](/docs/app/building-your-application/routing/parallel-routes#slots) | 名前付きスロット | -| [`(.)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 同じレベルでインターセプト | -| [`(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 1レベル上でインターセプト | -| [`(..)(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 2レベル上でインターセプト | -| [`(...)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | rootからインターセプト | +| | | +| ---------------------------------------------------------------------------------------------- | ----------------------------- | +| [`@folder`](/docs/app/building-your-application/routing/parallel-routes#slots) | 名前付きスロット | +| [`(.)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 同じレベルのインターセプト | +| [`(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 1つ上のレベルのインターセプト | +| [`(..)(..)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | 2つ上のレベルのインターセプト | +| [`(...)folder`](/docs/app/building-your-application/routing/intercepting-routes#convention) | rootからのインターセプト | ### メタデータファイルの規約 {#metadata-file-conventions} #### アプリのアイコン {#app-icons} -| | | | -| --------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ----------------------------- | -| [`favicon`](/docs/app/api-reference/file-conventions/metadata/app-icons#favicon) | `.ico` | ファビコンファイル | -| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#icon) | `.ico` `.jpg` `.jpeg` `.png` `.svg` | アプリアイコンファイル | -| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたアプリアイコン | -| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#apple-icon) | `.jpg` `.jpeg`, `.png` | Appleアプリアイコンファイル | -| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたAppleアプリアイコン | +| | | | +| --------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------------- | +| [`favicon`](/docs/app/api-reference/file-conventions/metadata/app-icons#favicon) | `.ico` | Faviconファイル | +| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#icon) | `.ico` `.jpg` `.jpeg` `.png` `.svg` | アプリのアイコンファイル | +| [`icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたアプリのアイコン | +| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#apple-icon) | `.jpg` `.jpeg`, `.png` | Appleアプリのアイコンファイル | +| [`apple-icon`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたAppleアプリのアイコン | -#### Open GraphとTwitterの画像 {#open-graph-and-twitter-images} +#### Open GraphおよびTwitterの画像 {#open-graph-and-twitter-images} -| | | | -| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------------------------ | -| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#opengraph-image) | `.jpg` `.jpeg` `.png` `.gif` | Open Graph画像ファイル | -| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたOpen Graph画像 | -| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#twitter-image) | `.jpg` `.jpeg` `.png` `.gif` | Twitter画像ファイル | -| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたTwitter画像 | +| | | | +| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | -------------------------- | +| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#opengraph-image) | `.jpg` `.jpeg` `.png` `.gif` | Open Graphの画像ファイル | +| [`opengraph-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたOpen Graphの画像 | +| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#twitter-image) | `.jpg` `.jpeg` `.png` `.gif` | Twitterの画像ファイル | +| [`twitter-image`](/docs/app/api-reference/file-conventions/metadata/opengraph-image#generate-images-using-code-js-ts-tsx) | `.js` `.ts` `.tsx` | 生成されたTwitter画像 | #### SEO {#seo} @@ -134,35 +134,35 @@ description: 'Next.jsプロジェクトにおけるフォルダとファイル | | | | | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------- | -------------------- | -| [`_app`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-app) | `.js` `.jsx` `.tsx` | カスタムApp | -| [`_document`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-document) | `.js` `.jsx` `.tsx` | カスタムDocument | +| [`_app`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-app) | `.js` `.jsx` `.tsx` | カスタムアプリ | +| [`_document`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-document) | `.js` `.jsx` `.tsx` | カスタムドキュメント | | [`_error`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-error#more-advanced-error-page-customizing) | `.js` `.jsx` `.tsx` | カスタムエラーページ | | [`404`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-error#404-page) | `.js` `.jsx` `.tsx` | 404エラーページ | | [`500`](https://nextjs.org/docs/canary/pages/building-your-application/routing/custom-error#500-page) | `.js` `.jsx` `.tsx` | 500エラーページ | ### ルート {#routes} -| | | | -| ----------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------ | -| **フォルダの規約** | | | -| [`index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | ホームページ | -| [`folder/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | ネストページ | -| **ファイルの規約** | | | -| [`index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | ホームページ | -| [`file`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts) | `.js` `.jsx` `.tsx` | ネストページ | +| | | | +| ----------------------------------------------------------------------------------------------------------------------- | ------------------- | -------------------- | +| **フォルダーの規約** | | | +| [`index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | ホームページ | +| [`folder/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | 入れ子になったページ | +| **ファイルの規約** | | | +| [`index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts#index-routes) | `.js` `.jsx` `.tsx` | ホームページ | +| [`file`](https://nextjs.org/docs/canary/pages/building-your-application/routing/pages-and-layouts) | `.js` `.jsx` `.tsx` | 入れ子になったページ | ### 動的ルート {#dynamic-routes} -| | | | -| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------- | ------------------------------------------ | -| **フォルダの規約** | | | -| [`[folder]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | 動的ルートセグメント | -| [`[...folder]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | キャッチオールルートセグメント | -| [`[[...folder]]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | オプションのキャッチオールルートセグメント | -| **ファイルの規約** | | | -| [`[file]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | 動的ルートセグメント | -| [`[...file]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | キャッチオールルートセグメント | -| [`[[...file]]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | オプションのキャッチオールルートセグメント | +| | | | +| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------- | ---------------------------------- | +| **フォルダーの規約** | | | +| [`[folder]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | 動的ルートセグメント | +| [`[...folder]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | Catch-allルートセグメント | +| [`[[...folder]]/index`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | Optional catch-allルートセグメント | +| **ファイルの規約** | | | +| [`[file]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes) | `.js` `.jsx` `.tsx` | 動的ルートセグメント | +| [`[...file]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#catch-all-segments) | `.js` `.jsx` `.tsx` | Catch-allルートセグメント | +| [`[[...file]]`](https://nextjs.org/docs/canary/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments) | `.js` `.jsx` `.tsx` | Optional catch-allルートセグメント | @@ -170,36 +170,36 @@ description: 'Next.jsプロジェクトにおけるフォルダとファイル ## プロジェクトの組織化 {#organizing-your-project} -Next.jsは、[フォルダとファイルの規約](/docs/app/getting-started/project-structure)以外では、プロジェクトファイルの組織化や配置方法に対して**特に意見を持っていません**。しかし、プロジェクトを整理するためのいくつかの機能を提供しています。 +[フォルダーとファイルの規約](/docs/app/getting-started/project-structure)とは別に、Next.jsはプロジェクトファイルの整理や配置方法について特に意見を持たない**unopinionated**です。しかし、プロジェクトを整理するためのさまざまな機能を提供しています。 ### コロケーション {#colocation} -`app`ディレクトリ内では、[ネストフォルダ階層](/docs/app/building-your-application/routing#route-segments)がルート構造を定義します。各フォルダは、URLパス内の対応するセグメントにマッピングされるルートセグメントを表しています。 +`app`ディレクトリ内で、[入れ子になったフォルダーハイラルキー](/docs/app/building-your-application/routing#route-segments)がルート構造を定義します。各フォルダーは、URLパスと対応するルートセグメントを表しています。 -ただし、ルート構造はフォルダを通して定義されますが、`page.js`または`route.js`ファイルがルートセグメントに追加されるまでは、ルートは**公開されません**。 +ただし、ルート構造がフォルダーを通じて定義されている場合でも、`page.js`または`route.js`ファイルがルートセグメントに追加されるまでは、ルートは**公開アクセス不可能**です。 routeセグメントにpage.jsまたはroute.jsファイルが追加されるまでルートは公開されないことを示す図 -そして、ルートが公開されるときも、クライアントに送信されるのは`page.js`または`route.js`によって返される**コンテンツだけ**です。 +そして、ルートが公開アクセス可能になると、`page.js`または`route.js`によって返される**コンテンツのみ**がクライアントに送信されます。 page.jsとroute.jsファイルがルートを公開可能にする方法を示す図 -これにより、**プロジェクトファイル**を`app`ディレクトリ内のルートセグメントに**安全にコロケーション**することができ、誤ってルートになることはありません。 +これは、`app`ディレクトリ内のルートセグメント内に**プロジェクトファイル**を**安全にコロケーション**することができ、間違えてルーティングされることがないことを意味します。 ページセグメントにpage.jsまたはroute.jsファイルが含まれていてもコロケーションされたプロジェクトファイルはルートにならないことを示す図 **Good to know**: > -> - `app`内にプロジェクトファイルをコロケーションできますが、必ずしもそうする必要はありません。希望する場合は、[`app`ディレクトリの外に保持する](#store-project-files-outside-of-app)こともできます。 +> - `app`内にプロジェクトファイルを**配置**することができるとはいえ、配置しなければならないというわけではありません。希望する場合は、[それらを`app`ディレクトリの外部に保持することもできます。](#store-project-files-outside-of-app)。 -### プライベートフォルダ {#private-folders} +### プライベートフォルダー {#private-folders} -フォルダ名の前にアンダースコアを付けることで、プライベートフォルダを作成することができます: `_folderName` +プライベートフォルダーは、フォルダー名の前にアンダースコアを付けることで作成できます: `_フォルダ名` -これはフォルダがプライベートな実装の詳細であることを示し、ルーティングシステムによって考慮されるべきではなく、**フォルダとそのサブフォルダ全体が**ルーティングから除外されることを意味します。 +これにより、フォルダーがプライベート実装の詳細であることを示し、ルーティングシステムによって考慮されないべきであることを示します。このことでフォルダーとそのサブフォルダーすべてをルーティングから**外すことを選択**します。 プライベートフォルダを使用したフォルダ構成の例 -`app`ディレクトリ内のファイルは[デフォルトで安全にコロケーションされるため](#colocation)、コロケーションのためにプライベートフォルダは必要ありません。しかし、次のような場合に有用です: +`app`ディレクトリ内のファイルは[デフォルトで安全にコロケーションすることができる](/docs/app/building-your-application/routing#route-segments)ため、コロケーションのためにプライベートフォルダーは必要ありません。ただし、以下の目的で便利です。 -- UIロジックとルーティングロジックを分離する -- プロジェクトやNext.jsエコシステム全体で内部ファイルを一貫して整理する -- コードエディタでファイルを整理しグループ化する -- 将来のNext.jsのファイル規約との命名の衝突を避ける +- UIロジックをルーティングロジックから分離する +- プロジェクト全体やNext.jsエコシステム内で内部ファイルを一貫して整理する +- コードエディタ内でファイルをソートおよびグループ化する +- 将来のNext.jsファイルの命名規約との潜在的な命名の衝突を避ける > **Good to know**: > -> - フレームワークの規約ではありませんが、プライベートフォルダの外にあるファイルも同じアンダースコアのパターンを使うことで「プライベート」とマークすることを検討するかもしれません。 -> - フォルダ名の前に `%5F`(アンダースコアのURLエンコード形式)を付けることで、アンダースコアで始まるURLセグメントを作成できます: +> - フレームワークの規約ではありませんが、プライベートフォルダー以外のファイルも同じアンダースコアパターンを使用して「プライベート」としてマークすることを検討するかもしれません +> - アンダースコアで始まるURLセグメントを作成するには、フォルダー名の前に`%5F`(アンダースコアのURLエンコード形)を付けてください: `%5Fフォルダ名` +> - プライベートフォルダーを使用しない場合は、予期しない命名の衝突を防ぐためにNext.jsの[特殊ファイルの規約](/docs/app/getting-started/project-structure#routing-files)を知っておくと便利です。 -- `%5FfolderName` - > - プライベートフォルダを使用しない場合、Unexpectedな命名の衝突を防ぐためにNext.jsの[特別なファイルの規約](/docs/app/getting-started/project-structure#routing-files)を知っておくと便利です。 +### Route Groups {#route-groups} -### ルートグループ {#route-groups} +Route Groupsは、フォルダーを括弧で囲むことで作成されます: `(フォルダ名)` -ルートグループは、フォルダを丸括弧で囲むことで作成できます:`(folderName)` - -これはフォルダが整理目的であり、ルートのURLパスには**含まれない**ことを示します。 +これにより、フォルダーが組織目的のためであり、ルートのURLパスには**含まれないべきである**ことを示しています。 ルートグループを使用したフォルダ構成の例 -ルートグループは次のような場合に有用です: +Route Groupsは次のような場合に便利です。 -- [サイトのセクション、目的、チームごとにルートをグループ化します](/docs/app/building-your-application/routing/route-groups#organize-routes-without-affecting-the-url-path) -- 同じルートセグメントレベルでネストされたレイアウトを可能にする: - - [同じセグメント内で複数のネストされたレイアウトを作成する(複数のroot レイアウトを含む)](/docs/app/building-your-application/routing/route-groups#creating-multiple-root-layouts) +- [ルートをグループに分けて整理すること](/docs/app/building-your-application/routing/route-groups#organize-routes-without-affecting-the-url-path) 例:サイトセクションごと、目的ごと、チームごとに +- 同じルートセグメントレベルで入れ子になったレイアウトを有効にする: + - [同じセグメント内で複数のroot レイアウトを含む複数の入れ子のレイアウトを作成する](/docs/app/building-your-application/routing/route-groups#creating-multiple-root-layouts) - [共通セグメント内のルートのサブセットにレイアウトを追加する](/docs/app/building-your-application/routing/route-groups#opting-specific-segments-into-a-layout) ### `src`ディレクトリ {#src-directory} -Next.jsは、アプリケーションコード(`app`を含む)をオプションの[`src`ディレクトリ](/docs/app/building-your-application/configuring/src-directory)内に保存することをサポートしています。これにより、プロジェクトの構成ファイルが主にプロジェクトのルートにあるのに対して、アプリケーションコードを分離します。 +Next.jsは、アプリケーションコードをオプションの[`src`ディレクトリ](/docs/app/building-your-application/configuring/src-directory)内に保存することをサポートしています。これは、プロジェクトのrootにある設定ファイルからアプリケーションコードを分離します。 `src`ディレクトリを使用したフォルダ構成の例 **Good to know**: 以下の例では、`components`や`lib`フォルダを一般的なプレースホルダとして使用しており、この命名には特別なフレームワークの意味はありません。プロジェクトによっては`ui`、`utils`、`hooks`、`styles`などのフォルダを使用することがあります。 +> **Good to know**: 以下の例では、`components`や`lib`フォルダーをジェネラライズされたプレースホルダーとして使用しています。これらの名前には特別なフレームワークの意義はなく、あなたのプロジェクトでは`ui`、`utils`、`hooks`、`styles`など他のフォルダーを使用するかもしれません。 -#### `app`の外にプロジェクトファイルを格納する {#store-project-files-outside-of-app} +#### プロジェクトファイルを`app`の外に保存する {#store-project-files-outside-of-app} -この戦略では、すべてのアプリケーションコードを**プロジェクトのルート**内の共有フォルダに保存し、`app`ディレクトリを純粋にルーティング目的のために保ちます。 +この戦略では、すべてのアプリケーションコードを**プロジェクトのroot**にある共有フォルダーに保存し、`app`ディレクトリを純粋にルーティング目的に利用します。 appの外にプロジェクトファイルがあるフォルダ構成の例 -#### `app`内部の最上位フォルダ内にプロジェクトファイルを格納する {#store-project-files-in-top-level-folders-inside-of-app} +#### プロジェクトファイルを`app`内のトップレベルフォルダーに保存する {#store-project-files-in-top-level-folders-inside-of-app} -この戦略では、アプリケーションコードを`app`ディレクトリの**ルート**内の共有フォルダに保存します。 +この戦略では、すべてのアプリケーションコードを**`app`ディレクトリのroot**にある共有フォルダーに保存します。 `app`の内部にプロジェクトファイルがあるフォルダ構成の例 -#### 機能またはルートごとにプロジェクトファイルを分割する {#split-project-files-by-feature-or-route} +#### プロジェクトファイルを機能やルートごとに分割する {#split-project-files-by-feature-or-route} -この戦略では、グローバルに共有されるアプリケーションコードを`app`ディレクトリのルートに保存し、より具体的なアプリケーションコードをルートセグメントごとに**分割**して使用します。 +この戦略では、グローバルに共有されるアプリケーションコードをrootの`app`ディレクトリに保存し、特定のアプリケーションコードを使用するルートセグメントに**分割**します。 機能またはルートごとに分割されたプロジェクトファイルを持つフォルダ構成の例 + + + + +```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 レイアウト](/docs/app/api-reference/file-conventions/layout#root-layouts)と呼ばれます。root レイアウトは**必須**であり、`html`および`body`タグを含める必要があります。 + +## ネストされたルートの作成 {#creating-a-nested-route} + +ネストされたルートは、複数のURLセグメントで構成されるルートです。たとえば、`/blog/[slug]`ルートは、3つのセグメントで構成されています: + +- `/` (Root Segment) +- `blog` (Segment) +- `[slug]` (Leaf Segment) + +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 ( +
    + {posts.map((post) => ( + + ))} +
+ ) +} +``` + +
+
+ + + +```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 ( +
    + {posts.map((post) => ( + + ))} +
+ ) +} +``` + +
+
+ +フォルダーを引き続きネストして、ネストされたルートを作成できます。たとえば、特定のブログ記事のルートを作成するには、`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](/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,10} 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,10} 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/04-images-and-fonts.mdx b/docs/01-app/01-getting-started/04-images-and-fonts.mdx new file mode 100644 index 00000000..5ece0d1a --- /dev/null +++ b/docs/01-app/01-getting-started/04-images-and-fonts.mdx @@ -0,0 +1,433 @@ +--- +title: '画像とフォントを最適化する方法' +nav_title: 'Images and Fonts' +description: '画像とフォントを最適化する方法を学びましょう。' +related: + title: 'API Reference' + description: 'このページで言及されている機能について詳しく知るには、API Reference をお読みください。' + links: + - app/api-reference/components/font + - app/api-reference/components/image +--- + +Next.jsには、自動的な画像とフォントの最適化機能が備わっており、パフォーマンスとユーザーエクスペリエンスが向上します。このページでは、それらの使用方法について説明します。 + +## 静的アセットの取り扱い {#handling-static-assets} + +画像やフォントなどの静的ファイルは、ルートディレクトリの`public`というフォルダに保存できます。`public`内のファイルは、ベースURL(`/`)を開始としてコードで参照できます。 + +appフォルダとpublicフォルダを示すフォルダ構造 + +## 画像の最適化 {#optmizing-images} + +Next.jsの[``](/docs/app/building-your-application/optimizing/images)コンポーネントは、HTMLの``要素を拡張して以下を提供します: + +- **サイズの最適化:** WebPやAVIFなどの現代的な画像フォーマットを使用して、各デバイスに適したサイズの画像を自動的に提供 +- **視覚的な安定性:** 画像がロードされる際に[レイアウトシフト](https://web.dev/articles/cls)を自動的に防止 +- **ページの高速読み込み:** 標準のブラウザの怠惰な読み込みを使用して画像がビューポートに入ったときのみロードし、任意のぼかしフィルアッププレースホルダーと共に +- **アセットの柔軟性:** リモートサーバに保存された画像さえもオンデマンドでサイズ変更 + +``を使用し始めるには、`next/image`からインポートし、コンポーネント内でレンダリングします。 + + + + +```tsx title="app/page.tsx" switcher +import Image from 'next/image' + +export default function Page() { + return +} +``` + + + + +```jsx title="app/page.js" switcher +import Image from 'next/image' + +export default function Page() { + return +} +``` + + + + +`src`プロパティは[ローカル](#local-images)または[リモート](#remote-images)画像のどちらかにすることができます。 + +### ローカル画像 {#local-images} + +ローカル画像を使用するには、`.jpg`、`.png`、または`.webp`画像ファイルを[`public`フォルダ](#handling-static-assets)から`import`します。 + + + + +```tsx title="app/page.tsx" switcher +import Image from 'next/image' +import profilePic from './me.png' + +export default function Page() { + return ( + 著者の写真 + ) +} +``` + + + + +```jsx title="app/page.js" switcher +import Image from 'next/image' +import profilePic from './me.png' + +export default function Page() { + return ( + 著者の写真 + ) +} +``` + + + + +Next.jsは、インポートしたファイルに基づいて画像の固有の[`width`](/docs/app/api-reference/components/image#width)と[`height`](/docs/app/api-reference/components/image#height)を自動的に決定します。これらの値は画像の比率を決定し、画像がロードされる間の[Cumulative Layout Shift](https://web.dev/articles/cls)を防ぐために使用されます。 + +### リモート画像 {#remote-images} + +リモート画像を使用するには、`src`プロパティにURL文字列を指定します。 + + + + +```tsx title="app/page.ts" switcher +import Image from 'next/image' + +export default function Page() { + return ( + 著者の写真 + ) +} +``` + + + + +```jsx title="app/page.js" switcher +import Image from 'next/image' + +export default function Page() { + return ( + 著者の写真 + ) +} +``` + + + + +Next.jsはビルドプロセス中にリモートファイルにアクセスできないため、[`width`](/docs/app/api-reference/components/image#width)、[`height`](/docs/app/api-reference/components/image#height)およびオプションで[`blurDataURL`](/docs/app/api-reference/components/image#blurdataurl)を手動で指定する必要があります。`width`と`height`の属性は、画像の正しいアスペクト比を推測し、画像の読み込みに起因するレイアウトの変化を避けるために使用されます。 + +次に、リモートサーバからの画像を安全に許可するために、[`next.config.js`](/docs/app/api-reference/config/next-config-js)にサポートされるURLパターンのリストを定義する必要があります。悪意のある使用を防ぐためにできるだけ具体的にしてください。たとえば、次の設定は特定のAWS S3バケットからの画像のみを許可します: + + + + +```ts title="next.config.ts" switcher +import { NextConfig } from 'next' + +const config: NextConfig = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 's3.amazonaws.com', + port: '', + pathname: '/my-bucket/**', + search: '', + }, + ], + }, +} + +export default config +``` + + + + +```js title="next.config.js" switcher +module.exports = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 's3.amazonaws.com', + port: '', + pathname: '/my-bucket/**', + search: '', + }, + ], + }, +} +``` + + + + +## フォントの最適化 {#optimizing-fonts} + +[`next/font`](/docs/app/api-reference/components/font)モジュールは、プライバシーとパフォーマンスを向上させるために、フォントを自動的に最適化し、外部ネットワークリクエストを排除します。 + +これは、*任意の*フォントファイルに対して**組み込みの自動セルフホスティング**を含んでいます。これにより、レイアウトシフトなしにウェブフォントを最適にロードすることができます。 + +`next/font`を使用し始めるには、[`next/font/local`](#local-fonts)または[`next/font/google`](#google-fonts)からインポートし、適切なオプションを使用して関数として呼び出し、フォントを適用したい要素の`className`を設定します。例: + + + + +```tsx title="app/layout.tsx" highlight={1,3-5,9} switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" highlight={1,3-5,9} switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function Layout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +### Google フォント {#google-fonts} + +任意のGoogleフォントを自動的にセルフホストできます。フォントはデプロイに含まれ、デプロイと同じドメインから提供されるため、ユーザーがサイトを訪れるときにブラウザからGoogleへのリクエストは送信されません。 + +Googleフォントの使用を開始するには、`next/font/google`から選択したフォントをインポートします: + + + + +```tsx title="app/layout.tsx" switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +import { Geist } from 'next/font/google' + +const geist = Geist({ + subsets: ['latin'], +}) + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +最良のパフォーマンスと柔軟性のために、[可変フォント](https://fonts.google.com/variablefonts)を使用することをお勧めします。しかし、可変フォントを使用できない場合は、**ウェイトを指定する必要があります**: + + + + +```tsx title="app/layout.tsx" switcher +import { Roboto } from 'next/font/google' + +const roboto = Roboto({ + weight: '400', + subsets: ['latin'], +}) + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" highlight={1,3-5,9} switcher +import { Roboto } from 'next/font/google' + +const roboto = Roboto({ + weight: '400', + subsets: ['latin'], +}) + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +### ローカルフォント {#local-fonts} + +ローカルフォントを使用するには、`next/font/local`からフォントをインポートし、[`public`フォルダ](#handling-static-assets)内のローカルフォントファイルの`src`を指定します。 + + + + +```tsx title="app/layout.tsx" switcher +import localFont from 'next/font/local' + +const myFont = localFont({ + src: './my-font.woff2', +}) + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +import localFont from 'next/font/local' + +const myFont = localFont({ + src: './my-font.woff2', +}) + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +単一のフォントファミリーに対して複数のファイルを使用したい場合、`src`は配列にすることができます: + +```js +const roboto = localFont({ + src: [ + { + path: './Roboto-Regular.woff2', + weight: '400', + style: 'normal', + }, + { + path: './Roboto-Italic.woff2', + weight: '400', + style: 'italic', + }, + { + path: './Roboto-Bold.woff2', + weight: '700', + style: 'normal', + }, + { + path: './Roboto-BoldItalic.woff2', + weight: '700', + style: 'italic', + }, + ], +}) +``` diff --git a/docs/01-app/01-getting-started/05-css-and-styling.mdx b/docs/01-app/01-getting-started/05-css-and-styling.mdx new file mode 100644 index 00000000..4b21c33e --- /dev/null +++ b/docs/01-app/01-getting-started/05-css-and-styling.mdx @@ -0,0 +1,640 @@ +--- +title: 'アプリケーションでCSSを使用する方法' +nav_title: 'CSSとスタイリング' +description: 'CSS Modules、グローバルCSS、Tailwind CSSなど、アプリケーションにCSSを追加するさまざまな方法について学びます' +related: + title: 'APIリファレンス' + description: 'このページで紹介されている機能について詳しくは、APIリファレンスを参照してください' + links: + - app/api-reference/config/next-config-js/sassOptions + - architecture/nextjs-compiler +--- + +Next.jsは、アプリケーションで次の方法を使ってCSSを使用できます: + +- [CSS Modules](#css-modules) +- [グローバルCSS](#global-css) +- [Tailwind CSS](#tailwind-css) +- [Sass](#sass) +- [CSS-in-JS](#css-in-js) +- [外部スタイルシート](#external-stylesheets) + +このページでは、これらの各アプローチの使用方法を案内します。 + +## CSS Modules {#css-modules} + +CSS Modulesは、一意のクラス名を生成することでCSSをローカルスコープにします。これにより、異なるファイルで同じクラスを使用しても衝突を心配する必要がありません。 + +CSS Modulesの使用を開始するには、`.module.css`拡張子の新しいファイルを作成し、`app`ディレクトリ内の任意のコンポーネントにインポートしてください: + +```css title="app/blog/styles.module.css" +.blog { + padding: 24px; +} +``` + + + + +```tsx title="app/blog/page.tsx" switcher +import styles from './styles.module.css' + +export default function Page({ children }: { children: React.ReactNode }) { + return
{children}
+} +``` + +
+ + +```jsx title="app/blog/page.js" switcher +import styles from './styles.module.css' + +export default function Page({ children }) { + return
{children}
+} +``` + +
+
+ +## グローバルCSS {#global-css} + +グローバルCSSを使用して、アプリケーション全体にスタイルを適用することができます。 + +グローバルスタイルを使用するには、新しいCSSファイルを作成します。例えば、`app/global.css`: + +```css title="app/global.css" +body { + padding: 20px 20px 60px; + max-width: 680px; + margin: 0 auto; +} +``` + +rootレイアウト(`app/layout.js`)でこのファイルをインポートし、アプリケーション内の**すべてのルート**にスタイルを適用します: + + + + +```tsx title="app/layout.tsx" switcher +// これらのスタイルは、アプリケーション内のすべてのルートに適用されます +import './global.css' + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +// これらのスタイルは、アプリケーション内のすべてのルートに適用されます +import './global.css' + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +> **Good to know:** グローバルスタイルは、`app`ディレクトリ内の任意のレイアウト、ページ、またはコンポーネントにインポートできます。しかし、Next.jsはスタイルシートを統合するためにReactのビルトインサポートを使用しています。このビルトインサポートは、ルート間を移動する際にスタイルシートを削除しません。したがって、*本当に*グローバルなCSSにはグローバルスタイルを、スコープされたCSSには[CSS Modules](#css-modules)を使用することをお勧めします。 + +## Tailwind CSS {#tailwind-css} + +[Tailwind CSS](https://tailwindcss.com/)は、Next.jsとシームレスに統合されるユーティリティファーストのCSSフレームワークです。 + +### Tailwindのインストール {#installing-tailwind} + +Tailwindを使用し始めるには、Tailwind CSSのパッケージをインストールし、`init`コマンドを実行して`tailwind.config.js`と`postcss.config.js`のファイルを生成します: + +```bash title="Terminal" +npm install -D tailwindcss postcss autoprefixer +npx tailwindcss init -p +``` + +### Tailwindの設定 {#configuring-tailwind} + +Tailwindの設定ファイル内で、Tailwindのクラス名を使用するファイルのパスを追加します: + + + + +```ts title="tailwind.config.ts" highlight={5-7} switcher +import type { Config } from 'tailwindcss' + +const config: Config = { + content: [ + './app/**/*.{js,ts,jsx,tsx,mdx}', + // `src`ディレクトリを使用している場合: + './src/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: {}, + }, + plugins: [], +} +export default config +``` + + + + +```js title="tailwind.config.js" highlight={4-6} switcher +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + './app/**/*.{js,ts,jsx,tsx,mdx}', + // `src`ディレクトリを使用している場合: + './src/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: {}, + }, + plugins: [], +} +``` + + + + +### Tailwindの使用 {#using-tailwind} + +[Tailwindのディレクティブ](https://tailwindcss.com/docs/functions-and-directives#directives)を[グローバルスタイルシート](#global-css)に追加します: + +```css title="app/globals.css" +@tailwind base; +@tailwind components; +@tailwind utilities; +``` + +次に、スタイルを[ルートレイアウト](/docs/app/api-reference/file-conventions/layout#root-layouts)でインポートします: + + + + +```tsx title="app/layout.tsx" switcher +import type { Metadata } from 'next' + +// これらのスタイルは、アプリケーションのすべてのルートに適用されます +import './globals.css' + +export const metadata: Metadata = { + title: 'Create Next App', + description: 'Generated by create next app', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +// これらのスタイルは、アプリケーションのすべてのルートに適用されます +import './globals.css' + +export const metadata = { + title: 'Create Next App', + description: 'Generated by create next app', +} + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +最後に、アプリケーションでTailwindのユーティリティクラスを書き始めることができます。 + + + + +```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!

+} +``` + +
+
+ +## Sass {#sass} + +Next.jsは、[`.scss`](https://sass-lang.com/documentation/syntax/#scss)と[`.sass`](https://sass-lang.com/documentation/syntax#the-indented-syntax)の両方の拡張子と構文を使用して[Sass](https://sass-lang.com/)と統合されます。 + +また、[CSS Modules](#css-modules)と`.module.scss`または`.module.sass`の拡張子を使って、コンポーネントレベルでのSassを使用することもできます。 + +### Sassのインストール {#installing-sass} + +Sassを使用し始めるには、`sass`パッケージをインストールします: + +```bash title="Terminal" +npm install --save-dev sass +``` + +### Sassオプションのカスタマイズ {#customizing-sass-options} + +Sassオプションを設定したい場合は、`next.config.js`で[`sassOptions`](/docs/app/api-reference/config/next-config-js/sassOptions)オプションを使用します: + + + + +```ts title="next.config.ts" switcher +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + sassOptions: { + additionalData: `$var: red;`, + }, +} + +export default nextConfig +``` + + + + +```js title="next.config.js" switcher +/** @type {import('next').NextConfig} */ + +const nextConfig = { + sassOptions: { + additionalData: `$var: red;`, + }, +} + +module.exports = nextConfig +``` + + + + +## CSS-in-JS {#css-in-js} + +> **警告:** 実行時JavaScriptを必要とするCSS-in-JSライブラリは、現時点ではReactのServer Componentsでサポートされていません。Server ComponentsやStreamingのような新しいReact機能とCSS-in-JSを使用するには、ライブラリアの作者が最新のReactバージョンをサポートする必要があります。 + +以下のライブラリは、`app`ディレクトリの**Client Components**でサポートされています(アルファベット順): + +- [`ant-design`](https://ant.design/docs/react/use-with-next#using-app-router) +- [`chakra-ui`](https://chakra-ui.com/getting-started/nextjs-app-guide) +- [`@fluentui/react-components`](https://react.fluentui.dev/?path=/docs/concepts-developer-server-side-rendering-next-js-appdir-setup--page) +- [`kuma-ui`](https://kuma-ui.com) +- [`@mui/material`](https://mui.com/material-ui/guides/next-js-app-router/) +- [`@mui/joy`](https://mui.com/joy-ui/integrations/next-js-app-router/) +- [`pandacss`](https://panda-css.com) +- [`styled-jsx`](#styled-jsx) +- [`styled-components`](#styled-components) +- [`stylex`](https://stylexjs.com) +- [`tamagui`](https://tamagui.dev/docs/guides/next-js#server-components) +- [`tss-react`](https://tss-react.dev/) +- [`vanilla-extract`](https://vanilla-extract.style) + +以下のライブラリは現在サポート中です: + +- [`emotion`](https://github.com/emotion-js/emotion/issues/2928) + +Server Componentsをスタイル付けしたい場合は、[CSS Modules](#css-modules)や、[Tailwind CSS](#tailwind-css)のようなCSSファイルを出力するソリューションを使用することをお勧めします。 + +### CSS-in-JSの設定 {#configuring-css-in-js} + +CSS-in-JSを設定するために必要なこと: + +1. レンダリング中にすべてのCSSルールを収集する**スタイルレジストリ**を作成します。 +2. `useServerInsertedHTML`フックを使って、それらのルールを使用する可能性のあるコンテンツの前にルールを挿入します。 +3. 最初のサーバーサイドレンダリング中にアプリをスタイルレジストリでラップするClient Componentを作成します。 + +#### `styled-jsx` {#styled-jsx} + +アプリケーション用に`styled-jsx`を設定するには、新しいレジストリを作成します: + + + + +```tsx title="app/registry.tsx" switcher +'use client' + +import React, { useState } from 'react' +import { useServerInsertedHTML } from 'next/navigation' +import { StyleRegistry, createStyleRegistry } from 'styled-jsx' + +export default function StyledJsxRegistry({ + children, +}: { + children: React.ReactNode +}) { + // レイジー初期状態でスタイルシートを一度だけ作成 + // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state + const [jsxStyleRegistry] = useState(() => createStyleRegistry()) + + useServerInsertedHTML(() => { + const styles = jsxStyleRegistry.styles() + jsxStyleRegistry.flush() + return <>{styles} + }) + + return {children} +} +``` + + + + +```jsx title="app/registry.js" switcher +'use client' + +import React, { useState } from 'react' +import { useServerInsertedHTML } from 'next/navigation' +import { StyleRegistry, createStyleRegistry } from 'styled-jsx' + +export default function StyledJsxRegistry({ children }) { + // レイジー初期状態でスタイルシートを一度だけ作成 + // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state + const [jsxStyleRegistry] = useState(() => createStyleRegistry()) + + useServerInsertedHTML(() => { + const styles = jsxStyleRegistry.styles() + jsxStyleRegistry.flush() + return <>{styles} + }) + + return {children} +} +``` + + + + +次に、[ルートレイアウト](/docs/app/api-reference/file-conventions/layout#root-layouts)をレジストリでラップします: + + + + +```tsx title="app/layout.tsx" switcher +import StyledJsxRegistry from './registry' + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {children} + + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +import StyledJsxRegistry from './registry' + +export default function RootLayout({ children }) { + return ( + + + {children} + + + ) +} +``` + + + + +#### `styled-components` {#styled-components} + +`styled-components`を使用するには、`next.config.js`で有効にします: + + + + +```ts title="next.config.ts" switcher +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + compiler: { + styledComponents: true, + }, +} + +export default nextConfig +``` + + + + +```js title="next.config.js" switcher +/** @type {import('next').NextConfig} */ +const nextConfig = { + compiler: { + styledComponents: true, + }, +} +``` + + + + +次に、`styled-components` APIを使用して、レンダリング中に生成されたすべてのCSSスタイルルールを収集するグローバルなレジストリコンポーネントと、それらのルールを返す関数を作成します。そして、`useServerInsertedHTML`フックを使って、そのレジストリで収集されたスタイルをrootレイアウトの`` HTMLタグに注入します。 + + + + +```tsx title="lib/registry.tsx" switcher +'use client' + +import React, { useState } from 'react' +import { useServerInsertedHTML } from 'next/navigation' +import { ServerStyleSheet, StyleSheetManager } from 'styled-components' + +export default function StyledComponentsRegistry({ + children, +}: { + children: React.ReactNode +}) { + // レイジー初期状態でスタイルシートを一度だけ作成 + // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state + const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet()) + + useServerInsertedHTML(() => { + const styles = styledComponentsStyleSheet.getStyleElement() + styledComponentsStyleSheet.instance.clearTag() + return <>{styles} + }) + + if (typeof window !== 'undefined') return <>{children} + + return ( + + {children} + + ) +} +``` + + + + +```jsx title="lib/registry.js" switcher +'use client' + +import React, { useState } from 'react' +import { useServerInsertedHTML } from 'next/navigation' +import { ServerStyleSheet, StyleSheetManager } from 'styled-components' + +export default function StyledComponentsRegistry({ children }) { + // レイジー初期状態でスタイルシートを一度だけ作成 + // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state + const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet()) + + useServerInsertedHTML(() => { + const styles = styledComponentsStyleSheet.getStyleElement() + styledComponentsStyleSheet.instance.clearTag() + return <>{styles} + }) + + if (typeof window !== 'undefined') return <>{children} + + return ( + + {children} + + ) +} +``` + + + + +rootレイアウトの`children`をスタイルレジストリコンポーネントでラップします: + + + + +```tsx title="app/layout.tsx" switcher +import StyledComponentsRegistry from './lib/registry' + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {children} + + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +import StyledComponentsRegistry from './lib/registry' + +export default function RootLayout({ children }) { + return ( + + + {children} + + + ) +} +``` + + + + +## 外部スタイルシート {#external-stylesheets} + +外部パッケージによって公開されているスタイルシートは、`app`ディレクトリ内のどこにでも、またはコロケートされたコンポーネント内にインポートすることができます: + + + + +```tsx title="app/layout.tsx" switcher +import 'bootstrap/dist/css/bootstrap.css' + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} +``` + + + + +```jsx title="app/layout.js" switcher +import 'bootstrap/dist/css/bootstrap.css' + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} +``` + + + + +外部スタイルシートは、npmパッケージから直接インポートするか、コードベースにコロケートしてダウンロードする必要があります。``を使用することはできません。 diff --git a/docs/01-app/01-getting-started/06-data-fetching-and-streaming.mdx b/docs/01-app/01-getting-started/06-data-fetching-and-streaming.mdx new file mode 100644 index 00000000..a885be11 --- /dev/null +++ b/docs/01-app/01-getting-started/06-data-fetching-and-streaming.mdx @@ -0,0 +1,413 @@ +--- +title: 'データをフェッチしてストリームする方法' +nav_title: 'データのフェッチとストリーミング' +description: 'アプリケーションでデータ取得とコンテンツストリーミングを開始します。' +related: + title: 'APIリファレンス' + description: 'このページで紹介されている機能について、APIリファレンスを読んでさらに詳しく学びましょう。' + links: + - 'app/api-reference/functions/fetch' + - 'app/api-reference/file-conventions/loading' +--- + +このページでは、[server component](#server-components)および[client component](#client-components)でのデータフェッチ方法を解説します。また、データに依存するコンテンツをどのように[ストリーム](#streaming)するかについても説明します。 + +## データのフェッチ {#fetching-data} + +### Server Components {#server-components} + +Server Componentsでデータをフェッチするには次の方法があります: + +1. [`fetch` API](#with-the-fetch-api)を使用する +2. [ORMやデータベース](#with-an-orm-or-database)を使用する + +#### `fetch` APIを使用する場合 {#with-the-fetch-api} + +`fetch` APIを使用してデータをフェッチするには、コンポーネントを非同期関数に変え、`fetch`呼び出しをawaitします。例えば: + + + + +```tsx title="app/blog/page.tsx" switcher +export default async function Page() { + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() + return ( +
    + {posts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+ + +```jsx title="app/blog/page.js" switcher +export default async function Page() { + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() + return ( +
    + {posts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+
+ +#### ORMやデータベースを使用する場合 {#with-an-orm-or-database} + +ORMやデータベースを使用してデータを取得するには、コンポーネントを非同期関数に変えて、その呼び出しをawaitします: + + + + +```tsx title="app/blog/page.tsx" switcher +import { db, posts } from '@/lib/db' + +export default async function Page() { + const allPosts = await db.select().from(posts) + return ( +
    + {allPosts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+ + +```jsx title="app/blog/page.js" switcher +import { db, posts } from '@/lib/db' + +export default async function Page() { + const allPosts = await db.select().from(posts) + return ( +
    + {allPosts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+
+ +### Client Components {#client-components} + +Client Componentsでデータをフェッチする方法は2つあります: + +1. Reactの[`use`フック](https://react.dev/reference/react/use)を使用する +2. [SWR](https://swr.vercel.app/)や[React Query](https://tanstack.com/query/latest)のようなコミュニティライブラリを使用する + +#### `use` フックを使用する場合 {#with-the-use-hook} + +Reactの[`use`フック](https://react.dev/reference/react/use)を使用して、サーバーからクライアントにデータを[ストリーム](#streaming)できます。まず、Server Componentsでデータをフェッチし、そのプロミスをClient Componentsにプロップとして渡します: + + + + +```tsx title="app/blog/page.tsx" switcher +import Posts from '@/app/ui/posts +import { Suspense } from 'react' + +export default function Page() { + // データ取得関数をawaitしないでください + const posts = getPosts() + + return ( + Loading...}> + + + ) +} +``` + + + + +```jsx title="app/blog/page.js" switcher +import Posts from '@/app/ui/posts +import { Suspense } from 'react' + +export default function Page() { + // データ取得関数をawaitしないでください + const posts = getPosts() + + return ( + Loading...}> + + + ) +} +``` + + + + +次に、Client Componentsで`use`フックを使用してプロミスを読み込みます: + + + + +```tsx title="app/ui/posts.tsx" switcher +'use client' +import { use } from 'react' + +export default function Posts({ posts }) { + const posts = use(posts) + + return ( +
    + {posts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+ + +```jsx title="app/ui/posts.js" switcher +'use client' +import { use } from 'react' + +export default function Posts({ posts }) { + const posts = use(posts) + + return ( +
    + {posts.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+
+ +上記の例では、``コンポーネントを[``境界](https://react.dev/reference/react/Suspense)でラップする必要があります。これは、プロミスが解決されるまでフォールバックが表示されることを意味します。[ストリーミング](#streaming)についてさらに学びましょう。 + +#### コミュニティライブラリ {#community-libraries} + +[SWR](https://swr.vercel.app/)や[React Query](https://tanstack.com/query/latest)のようなコミュニティライブラリを使用して、Client Components内でデータを取得できます。これらのライブラリは、キャッシュ、ストリーミング、およびその他の機能について独自のセマンティクスを持っています。例えば、SWRを使用した場合: + + + + +```tsx title="app/blog/page.tsx" switcher +'use client' +import useSWR from 'swr' + +const fetcher = (url) => fetch(url).then((r) => r.json()) + +export default function BlogPage() { + const { data, error, isLoading } = useSWR( + 'https://api.vercel.app/blog', + fetcher + ) + + if (isLoading) return
Loading...
+ if (error) return
Error: {error.message}
+ + return ( +
    + {data.map((post: { id: string; title: string }) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+ + +```jsx title="app/blog/page.js" switcher +'use client' +import useSWR from 'swr' + +const fetcher = (url) => fetch(url).then((r) => r.json()) + +export default function BlogPage() { + const { data, error, isLoading } = useSWR( + 'https://api.vercel.app/blog', + fetcher + ) + + if (isLoading) return
Loading...
+ if (error) return
Error: {error.message}
+ + return ( +
    + {data.map((post) => ( +
  • {post.title}
  • + ))} +
+ ) +} +``` + +
+
+ +## ストリーミング {#streaming} + +> **警告:** サーバーコンポーネントで`async/await`を使用する際には、アプリケーションの[`dynamicIO`設定オプション](/docs/app/api-reference/config/next-config-js/dynamicIO)が有効になっていることが前提です。このフラグはNext.js 15のcanaryで導入されました。 + +Server Componentsで`async/await`を使用すると、Next.jsは**動的レンダリング**に切り替わります。これは、データがユーザーのリクエストごとにサーバーでフェッチされ、レンダリングされることを意味します。遅いデータリクエストがある場合、ルート全体がレンダリングをブロックされます。 + +初期ロード時間とユーザー体験を改善するために、ストリーミングを使用してページのHTMLを小さなチャンクに分割し、そのチャンクをサーバーからクライアントへ徐々に送信できます。 + +ストリーミングを使用したサーバーレンダリングの動作 + +アプリケーションでストリーミングを実装する方法は2つあります: + +1. [`loading.js`ファイル](#with-loading-js)を使用する +2. Reactの[``コンポーネント](#with-suspense)を使用する + +### `loading.js`を使用する {#with-loading-js} + +ページと同じフォルダーに`loading.js`ファイルを作成して、データ取得中に**ページ全体**をストリームします。例えば、`app/blog/page.js`をストリームするには、`app/blog`フォルダー内にファイルを追加します。 + +loading.jsファイルを含むブログフォルダ構造 + + + + +```tsx title="app/blog/loading.tsx" switcher +export default function Loading() { + // ここで読み込みUIを定義します + return
Loading...
+} +``` + +
+ + +```jsx title="app/blog/loading.js" switcher +export default function Loading() { + // ここで読み込みUIを定義します + return
Loading...
+} +``` + +
+
+ +ナビゲーション時に、ページがレンダリングされるまでユーザーにはすぐにレイアウトと[読み込み状態](#creating-meaningful-loading-states)が表示されます。新しいコンテンツはレンダリング完了後に自動的にスワップされます。 + +ロード中のUI + +舞台裏では、`loading.js`は`layout.js`内にネストされ、`page.js`ファイルとその下の子を自動的に``境界でラップします。 + +loading.jsの概要 + +このアプローチはルートセグメント(レイアウトとページ)に対してうまく機能しますが、より細かいストリーミングには``を使用できます。 + +### ``を使用する {#with-suspense} + +``を使用すると、ページのどの部分をストリームするかをより細かく制御できます。例えば、``境界外のページコンテンツを即座に表示し、境界内のブログ投稿リストをストリームすることができます。 + + + + +```tsx title="app/blog/page.tsx" switcher +import { Suspense } from 'react' +import BlogList from '@/components/BlogList' +import BlogListSkeleton from '@/components/BlogListSkeleton' + +export default function BlogPage() { + return ( +
+ {/* このコンテンツは即座にクライアントに送信されます */} +
+

ブログへようこそ

+

最新の投稿を以下でお読みください。

+
+
+ {/* 境界でラップされたコンテンツはストリームされます */} + }> + + +
+
+ ) +} +``` + +
+ + +```jsx title="app/blog/page.js" switcher +import { Suspense } from 'react' +import BlogList from '@/components/BlogList' +import BlogListSkeleton from '@/components/BlogListSkeleton' + +export default function BlogPage() { + return ( +
+ {/* このコンテンツは即座にクライアントに送信されます */} +
+

ブログへようこそ

+

最新の投稿を以下でお読みください。

+
+
+ {/* 境界でラップされたコンテンツはストリームされます */} + }> + + +
+
+ ) +} +``` + +
+
+ +### 意味のある読み込み状態を作成する {#creating-meaningful-loading-states} + +インスタントロード状態は、ナビゲーション後にユーザーに即座に表示されるフォールバックUIです。最高のユーザー体験のために、意味があり、アプリが応答しているとユーザーに理解させるような読み込み状態を設計することをお勧めします。例えば、スケルトンやスピナー、または将来の画面のカバーフォトやタイトルなどの小さいが意味のある部分を使用できます。 + +開発中は、[React Devtools](https://react.dev/learn/react-developer-tools)を使用してコンポーネントの読み込み状態をプレビューおよびインスペクトすることができます。 diff --git a/docs/01-app/01-getting-started/index.mdx b/docs/01-app/01-getting-started/index.mdx index aefaba98..e03727d6 100644 --- a/docs/01-app/01-getting-started/index.mdx +++ b/docs/01-app/01-getting-started/index.mdx @@ -1,9 +1,4 @@ --- -title: 'Getting Started - App Router' -sidebar_label: 'Getting Started' -description: 'Next.jsのApp Routerを使ってフルスタックWebアプリケーションを作成する方法を学びましょう。' +title: '開始する' +description: 'Next.js App RouterでフルスタックのWebアプリケーションを作成する方法を学びます。' --- - -{/* NOTE: この は手動で追加しています。自動翻訳等で更新され消えてしまった場合、必要に応じて再度追加しなおしてください */} - - 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 795afc39..e2b043ed 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)を使用する -- [`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)を使用する +- [`` コンポーネントを使用する](#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) -このページでは、それぞれのオプションの使用方法について説明し、ナビゲーションの仕組みを詳しく見ていきます。 +このページではこれらのオプションを使用する方法と、ナビゲーションがどのように機能するのかを詳しく説明します。 ## `` コンポーネント {#link-component} -``は、HTMLの`
`タグを拡張し、[プリフェッチ](#2-prefetching)とクライアントサイドでのルート間ナビゲーションを提供する組み込みのコンポーネントです。Next.jsでルート間をナビゲートする主な推奨方法です。 +``は、HTMLの``タグを拡張して、[プリフェッチ](#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`フックを使うと、[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)を参照してください。 -> **推奨事項:** 特定の要件がない限り、ルート間をナビゲートするためには``コンポーネントを使用してください。 +> **推奨**:特定の要件がない限り、ルート間のナビゲーションには``コンポーネントを使用することをお勧めします。 ## `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 }) { -> **知っておいてよい点**: +> **知っておくと良い情報**: > -> - `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で使用する場合は303(See Other)を返し、これは通常POSTリクエストの結果として成功ページにリダイレクトするために使用されます。 +> - `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} -ブラウザの履歴スタックの現在のエントリを置き換えるために使用します。ユーザーは前の状態に戻ることができません。例えば、アプリケーションのロケールを切り替えるには: +現在のエントリを履歴スタック上で置き換えるために使用します。ユーザーは前の状態に戻ることができません。たとえば、アプリケーションのロケールを切り替える場合: @@ -215,7 +229,7 @@ export function LocaleSwitcher() { const pathname = usePathname() function switchLocale(locale: string) { - // e.g. '/en/about' or '/fr/contact' + // 例: '/en/about' や '/fr/contact' const newPath = `/${locale}${pathname}` window.history.replaceState(null, '', newPath) } @@ -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はルートセグメントを[プリフェッチ](#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)をご覧ください。 -> **知っておいてよい点**: +> **知っておくと良い情報**: > -> - プリフェッチは開発環境では有効ではなく、本番環境でのみ有効です。 +> - プリフェッチは開発時には有効ではなく、本番環境でのみ有効です。 ### 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)と呼ばれるクライアント側のインメモリキャッシュを持っています。ユーザーがアプリ内をナビゲートする際、[プリフェッチ](#2-prefetching)されたルートセグメントと訪問済みのルートのReact Server Component Payloadがキャッシュに保存されます。 -つまり、ナビゲーション時には、可能な限りキャッシュが再利用され、新たなサーバーへのリクエストを行う代わりに、キャッシュが使用されます。これにより、リクエスト数とデータ転送量が削減され、パフォーマンスが向上します。 +これにより、ナビゲーション時に可能な限りキャッシュが再利用され、サーバーへの新しいリクエストが行われなくなり、パフォーマンスが向上し、リクエスト数とデータ転送量が削減されます。 -[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`レイアウトが保持されます。この動作は、同じ動的セグメント上の2つのルート間でも見られます。例えば、`/blog/[slug]/page`と`/blog/first`から`/blog/second`へのナビゲーションです。 部分的なレンダリングの仕組み -部分的なレンダリングがない場合、各ナビゲーションはクライアントですべてのページを再レンダリングさせます。変更されるセグメントのみをレンダリングすることで、データ転送量と実行時間が削減され、パフォーマンスが向上します。 +部分レンダリングがなければ、それぞれのナビゲーションでクライアント上で完全なページが再レンダリングされることになります。変更されたセグメントのみをレンダリングすることで、データ転送量と実行時間が削減され、パフォーマンスが向上します。 ### 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`に設定して、この処理を完全に無効にすることも可能です。この機能が無効化された場合、appルートと重複するpagesの動的ルートはデフォルトで適切にナビゲートされません。 diff --git a/docs/01-app/02-building-your-application/01-routing/05-error-handling.mdx b/docs/01-app/02-building-your-application/01-routing/05-error-handling.mdx index 15ef478b..252d7af7 100644 --- a/docs/01-app/02-building-your-application/01-routing/05-error-handling.mdx +++ b/docs/01-app/02-building-your-application/01-routing/05-error-handling.mdx @@ -1,28 +1,28 @@ --- title: 'エラーハンドリング' -description: '予期されたエラーの表示方法と未キャッチ例外のハンドリングについて学びます。' +description: '予想されるエラーを表示し、捕捉されない例外を処理する方法を学びます。' related: links: - app/api-reference/file-conventions/error --- -エラーは2つのカテゴリに分けることができます:**予期されたエラー** と **未キャッチ例外**: +エラーは2つのカテゴリに分けられます:**予想されるエラー**と**捕捉されない例外**です; -- **予期されたエラーを戻り値としてモデル化する**:Server Actionsで予期されたエラーには`try`/`catch`を使用しないでください。これらのエラーを管理し、クライアントに返すには`useFormState`を使います。 -- **予期しないエラーにはエラーボーダリを使用する**:予期しないエラーを処理し、フォールバックUIを提供するには、`error.tsx`および`global-error.tsx`ファイルを使用してエラーボーダリを実装します。 +- **予想されるエラーは戻り値としてモデリングする**:Server Actions では予想されるエラーに `try`/`catch` を使用することは避けます。これらのエラーを管理し、クライアントに返すために [`useActionState`](https://react.dev/reference/react/useActionState) を使用します。 +- **予期しないエラーにはエラーボーダリーを使用する**:予期しないエラーを処理し、フォールバック UI を提供するために、`error.tsx` および `global-error.tsx` ファイルを使用してエラーボーダリーを実装します。 -## 予期されたエラーの処理 {#handling-expected-errors} +## 予想されるエラーの処理 {#handling-expected-errors} -予期されたエラーとは、[サーバー側フォームバリデーション](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-form-validation)やリクエストの失敗など、アプリケーションの通常の操作中に発生する可能性があるエラーです。これらのエラーは明示的に処理し、クライアントに返すべきです。 +予想されるエラーは、通常のアプリケーション操作中に発生する可能性のあるエラーです。たとえば、[サーバーサイドのフォームバリデーション](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-form-validation) や失敗したリクエストなどです。これらのエラーは明示的に処理され、クライアントに返されるべきです。 -### Server Actionsからの予期されたエラーを処理する {#handling-expected-errors-from-server-actions} +### Server Actions からの予想されるエラーの処理 {#handling-expected-errors-from-server-actions} -`useFormState`フックを使用して、Server Actionsの状態を管理し、エラーを処理します。このアプローチは`try`/`catch`ブロックを避け、予期されたエラーを例外としてスローするのではなく、戻り値としてモデル化します。 +`useActionState` フックを使用して、サーバーアクションの状態を管理します。これにはエラー処理も含まれます。このアプローチでは、予想されるエラーに対し `try`/`catch` ブロックを使用せず、それらを例外としてスローするのではなく、戻り値としてモデリングします。 - + -```tsx title="app/actions.ts" switcher +```ts title="app/actions.ts" switcher 'use server' import { redirect } from 'next/navigation' @@ -32,7 +32,7 @@ export async function createUser(prevState: any, formData: FormData) { const json = await res.json() if (!res.ok) { - return { message: '正しいメールアドレスを入力してください' } + return { message: '有効なメールアドレスを入力してください' } } redirect('/dashboard') @@ -40,9 +40,9 @@ export async function createUser(prevState: any, formData: FormData) { ``` - + -```jsx title="app/actions.js" switcher +```js title="app/actions.js" switcher 'use server' import { redirect } from 'next/navigation' @@ -52,7 +52,7 @@ export async function createUser(prevState, formData) { const json = await res.json() if (!res.ok) { - return { message: '正しいメールアドレスを入力してください' } + return { message: '有効なメールアドレスを入力してください' } } redirect('/dashboard') @@ -62,7 +62,7 @@ export async function createUser(prevState, formData) { -その後、`useFormState`フックにアクションを渡し、返される`state`を使用してエラーメッセージを表示できます。 +次に、アクションを `useActionState` フックに渡し、返された `state` を使用してエラーメッセージを表示します。 @@ -70,7 +70,7 @@ export async function createUser(prevState, formData) { ```tsx title="app/ui/signup.tsx" highlight={11,18-20} switcher 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { createUser } from '@/app/actions' const initialState = { @@ -78,7 +78,7 @@ const initialState = { } export function Signup() { - const [state, formAction] = useFormState(createUser, initialState) + const [state, formAction, pending] = useActionState(createUser, initialState) return (
@@ -86,7 +86,7 @@ export function Signup() { {/* ... */}

{state?.message}

- +
) } @@ -98,7 +98,7 @@ export function Signup() { ```jsx title="app/ui/signup.js" highlight={11,18-20} switcher 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { createUser } from '@/app/actions' const initialState = { @@ -106,7 +106,7 @@ const initialState = { } export function Signup() { - const [state, formAction] = useFormState(createUser, initialState) + const [state, formAction, pending] = useActionState(createUser, initialState) return (
@@ -114,7 +114,7 @@ export function Signup() { {/* ... */}

{state?.message}

- +
) } @@ -123,13 +123,11 @@ export function Signup() {
-> **Good to know**: これらの例は、Next.js App Routerと一緒にバンドルされているReactの`useFormState`フックを使用しています。React 19を使用している場合は、`useActionState`を代わりに使用してください。詳細については[Reactドキュメント](https://react.dev/reference/react/useActionState)を参照してください。 - 返された状態を使用して、クライアントコンポーネントからトーストメッセージを表示することもできます。 -### Server Componentsからの予期されたエラーを処理する {#handling-expected-errors-from-server-components} +### サーバーコンポーネントからの予想されるエラーの処理 {#handling-expected-errors-from-server-components} -Server Component内でデータを取得する際には、応答を利用してエラーメッセージを条件付けてレンダリングするか、[`redirect`](/docs/app/building-your-application/routing/redirecting#redirect-function)を使用してください。 +Server Component 内でデータをフェッチする際には、レスポンスを利用してエラーメッセージを条件付きでレンダリングするか、[`redirect`](/docs/app/building-your-application/routing/redirecting#redirect-function) することができます。 @@ -166,25 +164,25 @@ export default async function Page() { -## 未キャッチ例外 {#uncaught-exceptions} +## 捕捉されない例外 {#uncaught-exceptions} -未キャッチ例外は、アプリケーションの通常のフロー中に発生するはずのないバグや問題を示す予期しないエラーです。これらはエラーをスローすることで処理され、エラーボーダリによってキャッチされます。 +捕捉されない例外は、アプリケーションの通常の流れの中で発生することが予期されないバグや問題を示すエラーです。これらはエラーとしてスローされ、エラーボーダリーによって捕捉されるべきです。 -- **共通:** root レイアウト下の未キャッチエラーを`error.js`で処理します。 -- **オプション:** ネストされた`error.js`ファイル(例:`app/dashboard/error.js`)で詳細な未キャッチエラーを処理します。 -- **まれ:** root レイアウトで未キャッチエラーを`global-error.js`で処理します。 +- **一般的な処理**: root レイアウト以下で、`error.js` で捕捉されなかったエラーを処理します。 +- **オプショナル**: ネストされた `error.js` ファイルで細かく捕捉されなかったエラーを処理します(例:`app/dashboard/error.js`)。 +- **非一般的な処理**: root レイアウト内で捕捉されなかったエラーを `global-error.js` で処理します。 -### エラーボーダリを使用する {#using-error-boundaries} +### エラーボーダリーの使用 {#using-error-boundaries} -Next.jsはエラーボーダリを使用して未キャッチ例外を処理します。エラーボーダリはそれらの子コンポーネント内のエラーをキャッチし、クラッシュしたコンポーネントツリーの代わりにフォールバックUIを表示します。 +Next.js はエラーボーダリーを使用して捕捉されない例外を処理します。エラーボーダリーは、その子コンポーネント内のエラーをキャッチし、クラッシュしたコンポーネントツリーの代わりにフォールバック UI を表示します。 -ルートセグメント内に`error.tsx`ファイルを追加し、Reactコンポーネントをエクスポートすることでエラーボーダリを作成します: +ルートセグメント内に `error.tsx` ファイルを追加し、React コンポーネントをエクスポートしてエラーボーダリーを作成します: ```tsx title="app/dashboard/error.tsx" switcher -'use client' // エラーボーダリはClient Componentsである必要があります +'use client' // エラーボーダリーはクライアントコンポーネントである必要があります import { useEffect } from 'react' @@ -196,20 +194,20 @@ export default function Error({ reset: () => void }) { useEffect(() => { - // エラーをエラーレポートサービスにログします + // エラーをエラーレポーティングサービスにログします console.error(error) }, [error]) return (
-

何かがうまくいきませんでした!

+

問題が発生しました!

) @@ -220,26 +218,26 @@ export default function Error({ ```jsx title="app/dashboard/error.js" switcher -'use client' // エラーボーダリはClient Componentsである必要があります +'use client' // エラーボーダリーはクライアントコンポーネントである必要があります import { useEffect } from 'react' export default function Error({ error, reset }) { useEffect(() => { - // エラーをエラーレポートサービスにログします + // エラーをエラーレポーティングサービスにログします console.error(error) }, [error]) return (
-

何かがうまくいきませんでした!

+

問題が発生しました!

) @@ -249,11 +247,11 @@ export default function Error({ error, reset }) {
-エラーを親エラーボーダリまで伝播させたい場合は、`error`コンポーネントのレンダリング時に`throw`することができます。 +親エラーボーダリーにエラーをバブルアップさせたい場合は、`error` コンポーネントをレンダリングする際に `throw` できます。 -### ネストされたルートでのエラー処理 {#handling-errors-in-nested-routes} +### ネストされたルート内のエラー処理 {#handling-errors-in-nested-routes} -エラーは最も近い親エラーボーダリに伝播します。これにより、[ルート階層](/docs/app/building-your-application/routing#component-hierarchy)の異なるレベルに`error.tsx`ファイルを配置することで詳細なエラーハンドリングが可能になります。 +エラーは最も近い親エラーボーダリーまでバブルアップします。これにより、[ルート階層](/docs/app/building-your-application/routing#component-hierarchy)の異なるレベルに `error.tsx` ファイルを配置することで、細かいエラーハンドリングが可能になります。 ネストされたエラーコンポーネントの階層`および``タグを定義する必要があります。 +非一般的ですが、root アプリディレクトリにある `app/global-error.js` を使用して、root レイアウトでエラーを処理できます。これは、[国際化](/docs/app/building-your-application/routing/internationalization) を活用している場合でもです。グローバルエラー UI は独自の `` および `` タグを定義する必要があります。アクティブなとき、root レイアウトまたはテンプレートを置き換えるためです。 ```tsx title="app/global-error.tsx" switcher -'use client' // エラーボーダリはClient Componentsである必要があります +'use client' // エラーボーダリーはクライアントコンポーネントである必要があります export default function GlobalError({ error, @@ -281,11 +279,11 @@ export default function GlobalError({ reset: () => void }) { return ( - // global-errorにはhtmlとbodyタグが含まれていなければなりません + // global-error はhtmlとbodyタグを含む必要があります -

何かがうまくいきませんでした!

- +

問題が発生しました!

+ ) @@ -296,15 +294,15 @@ export default function GlobalError({ ```jsx title="app/global-error.js" switcher -'use client' // エラーボーダリはClient Componentsである必要があります +'use client' // エラーボーダリーはクライアントコンポーネントである必要があります export default function GlobalError({ error, reset }) { return ( - // global-errorにはhtmlとbodyタグが含まれていなければなりません + // global-error はhtmlとbodyタグを含む必要があります -

何かがうまくいきませんでした!

- +

問題が発生しました!

+ ) 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 8fe84611..b855a940 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: 'リダイレクション' +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 component、server actions、route handler | 307 (一時的) または 303 (server action) | +| [`permanentRedirect`](#permanentredirect-function) | ミューテーションやイベント後にユーザーをリダイレクトする | server component、server actions、route handler | 308 (永続的) | +| [`useRouter`](#userouter-hook) | クライアントサイドのナビゲーションを実行 | client component のイベントハンドラー | N/A | +| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js` ファイル | 307 (一時的) または 308 (永続的) | +| [`NextResponse.redirect`](#nextresponseredirect-in-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) | クライアントサイドのナビゲーションを実行 | コンポーネント | N/A | +| [`redirects` in `next.config.js`](#redirects-in-nextconfigjs) | パスに基づいて受信リクエストをリダイレクトする | `next.config.js` ファイル | 307 (一時的) または 308 (永続的) | +| [`NextResponse.redirect`](#nextresponseredirect-in-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 で使用される場合、303 (See Other) を返します。これは POST リクエストの結果として成功ページにリダイレクトするときに一般的に使用されます。 +> - `redirect` は内部でエラーをスローするため、`try/catch` ブロックの外部で呼び出す必要があります。 +> - `redirect` はクライアントコンポーネントのレンダリングプロセス中に呼び出すことができますが、イベントハンドラー内では呼び出すことはできません。代わりに [`useRouter` hook](#userouter-hook) を使用できます。 +> - `redirect` は絶対URLを受け取り、外部リンクにリダイレクトするために使用することもできます。 +> - レンダリングプロセスの前にリダイレクトしたい場合は、[`next.config.js`](#redirects-in-nextconfigjs) または [ミドルウェア](#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') // ユーザー名のすべての参照を更新する - permanentRedirect(`/profile/${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,21 +139,21 @@ export async function updateUsername(username, formData) { // エラーを処理する } - revalidateTag('username') // ユーザー名のすべての参照を更新する - permanentRedirect(`/profile/${username}`) // 新しいユーザープロフィールに移動する + revalidateTag('username') // ユーザー名へのすべての参照を更新する + permanentRedirect(`/profile/${username}`) // 新しいユーザープロファイルに移動する } ``` -> **参考情報**: +> **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) または [ミドルウェア](#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`メソッドを使用できます。例えば: +クライアントコンポーネントのイベントハンドラー内でリダイレクトする必要がある場合は、`useRouter` フックの `push` メソッドを使用できます。以下はその例です: @@ -176,7 +176,7 @@ export default function Page() { return ( ) } @@ -195,7 +195,7 @@ export default function Page() { return ( ) } @@ -208,7 +208,7 @@ export default function Page() { -コンポーネント内でリダイレクトする必要がある場合、`useRouter`フックの`push`メソッドを使用できます。例えば: +コンポーネント内でリダイレクトする必要がある場合は、`useRouter` フックの `push` メソッドを使用できます。以下はその例です: @@ -221,7 +221,7 @@ export default function Page() { return ( ) } @@ -238,7 +238,7 @@ export default function Page() { return ( ) } @@ -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` は [path](/docs/app/api-reference/config/next-config-js/redirects#path-matching)、[header、cookie、およびクエリの一致](/docs/app/api-reference/config/next-config-js/redirects#header-cookie-and-query-matching)をサポートし、受信リクエストに基づいてユーザーを柔軟にリダイレクトできます。 -`redirects`を使用するには、`next.config.js`ファイルにオプションを追加します: +`next.config.js` ファイルに `redirects` オプションを追加して使用します: ```js title="next.config.js" module.exports = { @@ -283,7 +283,7 @@ module.exports = { destination: '/', permanent: true, }, - // ワイルドカードパスマッチング + // ワイルドカードパスのマッチング { source: '/blog/:slug', destination: '/news/:slug', @@ -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+) を管理するには、[ミドルウェア](/docs/app/building-your-application/routing/middleware) を使用してカスタムソリューションを作成することを検討してください。詳細は [大規模なリダイレクトの管理](#managing-redirects-at-scale-advanced) を参照してください。 +> - `redirects` はミドルウェアの **前** に実行されます。 -## `NextResponse.redirect` in Middleware {#nextresponse-redirect-in-middleware} +## ミドルウェアでの `NextResponse.redirect` {#nextresponse-redirect-in-middleware} -ミドルウェアを使用すると、リクエストが完了する前にコードを実行できます。そして、受信リクエストに基づいて`NextResponse.redirect`を使用して別のURLにリダイレクトします。これは、条件(例:認証、セッション管理など)に基づいてユーザーをリダイレクトする場合や、大量のリダイレクトがあります: +ミドルウェアを使用すると、リクエストが完了する前にコードを実行できます。その後、受信リクエストに基づいて、`NextResponse.redirect` を使用して異なる URL にリダイレクトします。これは、条件に基づいてユーザーをリダイレクトしたい場合(例:認証、セッション管理など)や、大量のリダイレクトを持つ場合に便利です。 -たとえば、ユーザーが認証されていない場合に`/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,28 +359,28 @@ export const config = { -> **参考情報**: +> **Good to know**: > -> - ミドルウェアは、`next.config.js`の`redirects`**後に**実行され、レンダリングの**前に**実行されます; +> - ミドルウェアは、`next.config.js` の `redirects` の **後**、レンダリングの **前** に実行されます。 -[Middleware](/docs/app/building-your-application/routing/middleware)のドキュメントを参照して、さらに情報をご覧ください。 +[ミドルウェア](/docs/app/building-your-application/routing/middleware) のドキュメントを参照してください。 -## 規模に応じたリダイレクト管理(高度) {#managing-redirects-at-scale-advanced} +## 大規模なリダイレクト管理(高度) {#managing-redirects-at-scale-advanced} -大量のリダイレクト(1000件以上)を管理するために、ミドルウェアを使用してカスタムソリューションを作成することを検討してください。これにより、アプリケーションを再デプロイすることなく、プログラムでリダイレクトを処理できます。 +多数のリダイレクト (1000+) を管理するために、ミドルウェアを使用してカスタムソリューションを作成することを検討するかもしれません。これにより、アプリケーションを再デプロイすることなくプログラムでリダイレクトを処理できます。 これを行うには、以下を考慮する必要があります: 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} -リダイレクトマップは、データベース(通常はキー・バリュー・ストア)またはJSONファイルに保存できるリダイレクトのリストです。 +リダイレクトマップは、キーと値のストアや 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)などのデータベースから読み取り、受信リクエストに基づいてユーザーをリダイレクトすることができます: +[ミドルウェア](/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) のようなデータ検索戦略を使用して、より大きなリダイレクトファイルまたはデータベースを読み取る **前に** リダイレクトが存在するかどうかを効率的にチェックします。 -前述の例では、生成されたブルームフィルターファイルをミドルウェアにインポートし、受信リクエストのパス名がブルームフィルターに存在するかどうかを確認します。 +前の例を考慮すると、生成されたブルームフィルターファイルをミドルウェアにインポートし、受信リクエストのパス名がブルームフィルターに存在するかを確認できます。 -存在する場合は、要求を[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 にユーザーをリダイレクトします。これにより、大きなリダイレクトファイルをミドルウェアにインポートする必要がなくなり、すべての受信リクエストの速度を低下させることが防げます。 - + -```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) { @@ -509,7 +509,7 @@ export async function middleware(request: NextRequest) { } } - // リダイレクトが見つからなかった場合、そのままリクエストを続行します + // リダイレクトが見つからない場合、リダイレクトせずにリクエストを続行します return NextResponse.next() } ``` @@ -522,23 +522,23 @@ 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) { @@ -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 ルートで: - + -```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/01-routing/15-internationalization.mdx b/docs/01-app/02-building-your-application/01-routing/15-internationalization.mdx index 1d78b7d3..ba1f5bd6 100644 --- a/docs/01-app/02-building-your-application/01-routing/15-internationalization.mdx +++ b/docs/01-app/02-building-your-application/01-routing/15-internationalization.mdx @@ -1,22 +1,22 @@ --- -title: '国際化' -description: '国際化されたルーティングと地域化されたコンテンツで複数言語のサポートを追加します' +title: 'Internationalization' +description: '国際化されたルーティングとローカライズされたコンテンツで複数の言語をサポートします。' --- -Next.jsは、コンテンツのルーティングとレンダリングを構成して、複数の言語をサポートすることを可能にします。異なるロケールにサイトを適応させることには、翻訳されたコンテンツ(地域化)と国際化されたルートが含まれます。 +Next.jsを使用すると、複数の言語をサポートするようにコンテンツのルーティングとレンダリングを設定できます。サイトをさまざまなロケールに適応させるためには、翻訳されたコンテンツ(ローカライゼーション)と国際化されたルートが含まれます。 ## 用語 {#terminology} -- **Locale:** 一連の言語および形式設定の優先事項の識別子。通常、ユーザーの好みの言語とおそらく地理的な地域が含まれます。 - - `en-US`: アメリカで話される英語 - - `nl-NL`: オランダで話されるオランダ語 - - `nl`: 特定の地域が指定されていないオランダ語 +- **ロケール:** 言語とフォーマットの設定を識別するための識別子。通常、ユーザーの希望する言語と、場合によっては地理的地域を含みます。 + - `en-US`: アメリカ合衆国で使用される英語 + - `nl-NL`: オランダで使用されるオランダ語 + - `nl`: 特定の地域を指定しないオランダ語 -## ルーティングの概要 {#routing-overview} +## ルーティング概要 {#routing-overview} -ブラウザでのユーザーの言語優先順位を使用して、どのロケールを使用するかを選択することをお勧めします。好みの言語を変更すると、アプリケーションに到着する`Accept-Language`ヘッダーが変更されます。 +ブラウザでユーザーの言語設定を使用して、使用するロケールを選択することをお勧めします。希望の言語を変更すると、アプリケーションへの受信`Accept-Language`ヘッダーが変更されます。 -例えば、以下のライブラリを使用して、受信する`Request`を見て、`Headers`、サポート予定のロケール、およびデフォルトのロケールに基づいて、どのロケールを選択するかを決定することができます。 +たとえば、次のライブラリを使用して、受信した`Request`を調べ、`Headers`、サポート予定のロケール、およびデフォルトのロケールに基づいてどのロケールを選択するかを判断できます。 ```js title="middleware.js" import { match } from '@formatjs/intl-localematcher' @@ -30,18 +30,18 @@ let defaultLocale = 'en-US' match(languages, locales, defaultLocale) // -> 'en-US' ``` -ルーティングはサブパス (`/fr/products`) またはドメイン (`my-site.fr/products`) を使用して国際化できます。この情報を使用して、[Middleware](/docs/app/building-your-application/routing/middleware)内でロケールに基づいてユーザーをリダイレクトすることができます。 +サブパス(`/fr/products`)またはドメイン(`my-site.fr/products`)を使って、ルーティングを国際化できます。この情報を使用して、[Middleware](/docs/app/building-your-application/routing/middleware)内でロケールに基づいてユーザーをリダイレクトできます。 ```js title="middleware.js" import { NextResponse } from "next/server"; let locales = ['en-US', 'nl-NL', 'nl'] -// 上記と同様にまたはライブラリを用いて、好みのロケールを取得する +// 上記と同様に、またはライブラリを使用して、希望のロケールを取得します function getLocale(request) { ... } export function middleware(request) { - // パス名にサポートされているロケールがあるかどうかを確認 + // パス名にサポートされているロケールが含まれているか確認します const { pathname } = request.nextUrl const pathnameHasLocale = locales.some( (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` @@ -49,41 +49,41 @@ export function middleware(request) { if (pathnameHasLocale) return - // ロケールがない場合はリダイレクト + // ロケールがない場合はリダイレクトします const locale = getLocale(request) request.nextUrl.pathname = `/${locale}${pathname}` - // 例: 受信リクエストが/productsの場合 - // 新しいURLは/en-US/productsになります + // 例:受信リクエストが /products の場合 + // 新しいURLは /en-US/products になります return NextResponse.redirect(request.nextUrl) } export const config = { matcher: [ - // すべての内部パス (_next) をスキップ + // すべての内部パス (_next) をスキップします '/((?!_next).*)', - // 任意: root (/) URL でのみ実行 + // オプション: ルート (/) URL のみに実行します // '/' ], } ``` -最後に、`app/`内のすべての特別なファイルが`app/[lang]`の下にネストされていることを確認してください。これにより、Next.js routerはルート内の異なるロケールを動的に処理し、`lang`パラメータをすべてのレイアウトとページに転送できるようになります。例えば: +最後に、`app/`内のすべての特別なファイルが`app/[lang]`の下にネストされていることを確認します。これにより、Next.js routerがルート内の異なるロケールを動的に処理し、`lang`パラメータをすべてのレイアウトとページに転送できるようになります。たとえば: ```jsx title="app/[lang]/page.js" -// 現在のロケールにアクセスできるようになります -// 例: /en-US/products -> `lang`は"en-US" +// 現在のロケールにアクセスできます +// 例:/en-US/products -> `lang`が"en-US"です export default async function Page({ params: { lang } }) { return ... } ``` -root レイアウトも新しいフォルダー(例: `app/[lang]/layout.js`)にネストできます。 +root レイアウトも新しいフォルダー内にネストできます(例:`app/[lang]/layout.js`)。 -## 地域化 {#localization} +## ローカライゼーション {#localization} -ユーザーの好みのロケールに基づいて表示されるコンテンツを変更する、つまり地域化はNext.jsに特有のものではありません。以下で説明するパターンは、任意のWebアプリケーションでも同様に機能します。 +ユーザーの希望するロケールに基づいて表示されるコンテンツを変更する、つまりローカライゼーションは、Next.jsに特有のものではありません。以下に説明するパターンは、任意のWebアプリケーションで同様に動作します。 -アプリケーション内で英語とオランダ語のコンテンツの両方をサポートしたいと仮定しましょう。いくつかのキーから地域化された文字列へのマッピングを提供するオブジェクトである2つの異なる「辞書」を管理するかもしれません。例えば: +アプリケーション内で英語とオランダ語の両方のコンテンツをサポートしたいと仮定します。異なる2つの「辞書」を維持することができます。辞書は、あるキーからローカライズされた文字列へのマッピングを提供するオブジェクトです。たとえば: ```json title="dictionaries/en.json" { @@ -101,7 +101,7 @@ root レイアウトも新しいフォルダー(例: `app/[lang]/layout.js`) } ``` -次に、要求されたロケールの翻訳をロードするための`getDictionary`関数を作成できます: +次に、リクエストされたロケールの翻訳をロードするための`getDictionary`関数を作成できます: ```jsx title="app/[lang]/dictionaries.js" import 'server-only' @@ -114,22 +114,22 @@ const dictionaries = { export const getDictionary = async (locale) => dictionaries[locale]() ``` -現在選択されている言語に基づいて、レイアウトやページ内で辞書を取得できます。 +現在選択されている言語を考慮して、レイアウトやページの中で辞書を取得できます。 ```jsx title="app/[lang]/page.js" import { getDictionary } from './dictionaries' export default async function Page({ params: { lang } }) { const dict = await getDictionary(lang) // en - return // カートに追加 + return // Add to Cart } ``` -`app/`ディレクトリ内のすべてのレイアウトとページがデフォルトで[Server Components](/docs/app/building-your-application/rendering/server-components)であるため、翻訳ファイルのサイズがクライアント側JavaScriptバンドルサイズに影響を与えることを心配する必要はありません。このコードは**サーバー上でのみ実行され**、結果として得られるHTMLのみがブラウザーに送信されます。 +`app/` ディレクトリ内のすべてのレイアウトとページはデフォルトで[Server Components](/docs/app/building-your-application/rendering/server-components)ですので、翻訳ファイルのサイズがクライアントサイドのJavaScriptバンドルサイズに影響を与えることを心配する必要はありません。このコードは**サーバーでのみ実行**され、その結果として生成されたHTMLのみがブラウザに送信されます。 ## 静的生成 {#static-generation} -特定のロケールセットに対して静的ルートを生成するには、`generateStaticParams`をページやレイアウトで使用します。例えば、root レイアウトでこれをグローバルに行うことができます: +特定のロケールセットに対して静的ルートを生成するには、ページやレイアウトに`generateStaticParams`を使用できます。たとえば、root レイアウトでグローバルに行うことができます: ```jsx title="app/[lang]/layout.js" export async function generateStaticParams() { @@ -147,7 +147,7 @@ export default function Root({ children, params }) { ## リソース {#resources} -- [Minimal i18n routing and translations](https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing) +- [Minimal i18n routing and translations](https://github.com/vercel/next.js/tree/canary/examples/i18n-routing) - [`next-intl`](https://next-intl-docs.vercel.app/docs/next-13) - [`next-international`](https://github.com/QuiiBz/next-international) - [`next-i18n-router`](https://github.com/i18nexus/next-i18n-router) 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 357b81e4..63ed1d44 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,11 +1,11 @@ --- -title: 'データ取得とキャッシュ' -nav_title: 'データ取得とキャッシュ' -description: 'Next.jsでサーバーまたはクライアントでデータを取得するためのベストプラクティスを学びましょう。' +title: 'データフェッチングとキャッシング' +nav_title: 'データフェッチングとキャッシング' +description: 'Next.jsでのサーバーまたはクライアントでのデータ取得のベストプラクティスを学びます。' ---
- + Examples - [Next.js Commerce](https://vercel.com/templates/next.js/nextjs-commerce) - [On-Demand ISR](https://on-demand-isr.vercel.app) @@ -13,17 +13,17 @@ description: 'Next.jsでサーバーまたはクライアントでデータを
-このガイドでは、Next.jsにおけるデータ取得とキャッシュの基本を実用的な例とベストプラクティスを示しながら説明します。 +このガイドでは、Next.jsにおけるデータフェッチングとキャッシングの基本を具体的な例とベストプラクティスを通じて説明します。 -Next.jsにおけるデータ取得の最小限の例を以下に示します: +以下はNext.jsでのデータ取得の最小限の例です。 ```tsx title="app/page.tsx" switcher export default async function Page() { - let data = await fetch('https://api.vercel.app/blog') - let posts = await data.json() + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() return (
    {posts.map((post) => ( @@ -39,8 +39,8 @@ export default async function Page() { ```jsx title="app/page.js" switcher export default async function Page() { - let data = await fetch('https://api.vercel.app/blog') - let posts = await data.json() + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() return (
      {posts.map((post) => ( @@ -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,17 +64,17 @@ 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`からの応答はデフォルトでキャッシュされません。 ```tsx title="app/page.tsx" switcher export default async function Page() { - let data = await fetch('https://api.vercel.app/blog') - let posts = await data.json() + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() return (
        {posts.map((post) => ( @@ -90,8 +90,8 @@ export default async function Page() { ```jsx title="app/page.js" switcher export default async function Page() { - let data = await fetch('https://api.vercel.app/blog') - let posts = await data.json() + const data = await fetch('https://api.vercel.app/blog') + const posts = await data.json() return (
          {posts.map((post) => ( @@ -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)を使用して更新できます。 +このルート内で他の[ダイナミックAPI](/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)によりキャッシュできます。 @@ -126,7 +126,7 @@ export const dynamic = 'force-dynamic' import { db, posts } from '@/lib/db' export default async function Page() { - let allPosts = await db.select().from(posts) + const allPosts = await db.select().from(posts) return (
            {allPosts.map((post) => ( @@ -144,7 +144,7 @@ export default async function Page() { import { db, posts } from '@/lib/db' export default async function Page() { - let allPosts = await db.select().from(posts) + const allPosts = await db.select().from(posts) return (
              {allPosts.map((post) => ( @@ -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)を使用して更新できます。 +このルート内で他の[ダイナミックAPI](/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`を明示的に使用する必要はありません。 -### クライアントでデータを取得する {#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)など)を利用することができます。 @@ -187,8 +187,8 @@ export function Posts() { useEffect(() => { async function fetchPosts() { - let res = await fetch('https://api.vercel.app/blog') - let data = await res.json() + const res = await fetch('https://api.vercel.app/blog') + const data = await res.json() setPosts(data) } fetchPosts() @@ -219,8 +219,8 @@ export function Posts() { useEffect(() => { async function fetchPosts() { - let res = await fetch('https://api.vercel.app/blog') - let data = await res.json() + const res = await fetch('https://api.vercel.app/blog') + const data = await res.json() setPosts(data) } fetchPosts() @@ -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`実行時にページを事前レンダリングすることができます。 +ページを`next build`を実行した際にプリレンダリングできるように応答をキャッシュするために`unstable_cache` APIを使用できます。 @@ -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](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)で無効化できます。 -### 複数の関数でデータを再利用する {#reusing-data-across-multiple-functions} +### 複数の関数間でデータを再利用する {#reusing-data-across-multiple-functions} -Next.jsは、`generateMetadata`や`generateStaticParams`といったAPIを使用します。これらのAPIでは、`page`で取得したデータを使う必要があります。 +Next.jsは、`generateMetadata`や`generateStaticParams`といったAPIを使用して、`page`で取得した同じデータを利用する必要があります。 -もし`fetch`を使用している場合、リクエストに`cache: 'force-cache'`を追加するとリクエストが[メモ化](/docs/app/building-your-application/caching#request-memoization)されます。これにより、同じオプションで同じURLを安全に呼び出すことができ、リクエストは1回のみ行われます。 +もし`fetch`を使用している場合、リクエストは`cache: 'force-cache'`を追加することで[メモ化](/docs/app/building-your-application/caching#request-memoization)できます。これは、同じURLを同じオプションで安全に呼び出せることを意味し、1つのリクエストしか行われません。 -> **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,47 +444,48 @@ 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内のリクエストが互いに依存し合う。これによりロード時間が長くなることがあります +- **並行**: ルート内のリクエストは先に開始され、データを同時にロードします。これによりデータロードにかかる総時間が短縮されます -#### 逐次データ取得 {#sequential-data-fetching} +#### 順次フェッチング {#sequential-data-fetching} -ネストされたコンポーネントがあり、各コンポーネントが独自にデータを取得する場合、これらのデータリクエストが[メモ化](/docs/app/building-your-application/caching#request-memoization)されていない場合、データ取得は逐次的に行われます。 +ネストされたコンポーネントがあり、それぞれのコンポーネントが自身のデータをフェッチする場合、これらのデータリクエストが[メモ化](/docs/app/building-your-application/caching#request-memoization)されていないと、データフェッチングは順次に行われます。 -このパターンが望ましい場合もあります。たとえば、`Playlists`コンポーネントは`Artist`コンポーネントがデータ取得を完了してからデータを取得し始めます。`Playlists`は`artistID` propに依存しているためです: +このパターンが望まれる場合があります。なぜなら1つのフェッチが他のフェッチの結果に依存するからです。例えば、`Playlists`コンポーネントは`Artist`コンポーネントのデータフェッチが完了しないとフェッチを開始しません。なぜなら、`Playlists`は`artistID` propに依存しているからです。 ```tsx title="app/artist/[username]/page.tsx" switcher export default async function Page({ - params: { username }, + params, }: { params: Promise<{ username: string }> }) { - // アーティスト情報の取得 + const { username } = await params + // アーティスト情報を取得 const artist = await getArtist(username) return ( <>

              {artist.name}

              - {/* Playlistsコンポーネントの読み込み中にフォールバックUIを表示 */} + {/* Playlistsコンポーネントがロードされる間、フォールバックUIを表示 */} Loading...}> {/* アーティストIDをPlaylistsコンポーネントに渡す */} @@ -490,7 +495,7 @@ export default async function Page({ } async function Playlists({ artistID }: { artistID: string }) { - // アーティストIDを使用してプレイリストを取得 + // アーティストIDを使用してプレイリストをフェッチ const playlists = await getArtistPlaylists(artistID) return ( @@ -507,14 +512,15 @@ async function Playlists({ artistID }: { artistID: string }) { ```jsx title="app/artist/[username]/page.js" switcher -export default async function Page({ params: { username } }) { - // アーティスト情報の取得 +export default async function Page({ params }) { + const { username } = await params + // アーティスト情報を取得 const artist = await getArtist(username) return ( <>

              {artist.name}

              - {/* Playlistsコンポーネントの読み込み中にフォールバックUIを表示 */} + {/* Playlistsコンポーネントがロードされる間、フォールバックUIを表示 */} Loading...}> {/* アーティストIDをPlaylistsコンポーネントに渡す */} @@ -524,7 +530,7 @@ export default async function Page({ params: { username } }) { } async function Playlists({ artistID }) { - // アーティストIDを使用してプレイリストを取得 + // アーティストIDを使用してプレイリストをフェッチ const playlists = await getArtistPlaylists(artistID) return ( @@ -540,19 +546,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)(ルートセグメント用)または[React ``](/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense)(ネストされたコンポーネント用)を使用して、結果がストリーミングされる間に即座に読み込み状態を表示することができます。 -これにより、データリクエストによってroute全体がブロックされるのを防ぎ、ユーザーは準備ができているページの部分と対話できるようになります。 +これにより、ルート全体がデータリクエストによってブロックされるのを防ぎ、ユーザーは準備ができたページの部分と対話できるようになります。 -#### 並列データ取得 {#parallel-data-fetching} +#### 並行データフェッチング {#parallel-data-fetching} -デフォルトで、レイアウトとページセグメントは並列にレンダリングされます。これにより、リクエストは並行して開始されます。 +デフォルトでは、レイアウトとページセグメントは並行でレンダリングされます。つまり、リクエストは並行して開始されます。 -しかし、`async`/`await`の特性上、同じセグメントまたはコンポーネント内で待たれるリクエストはそれ以下のリクエストをブロックします。 +しかし、`async`/`await`の性質上、同じセグメントやコンポーネント内で待機されたリクエストはその下にあるリクエストをブロックします。 -データを並列に取得するには、データを使用するコンポーネントの外側でリクエストを定義して積極的に開始します。これにより、両方のリクエストが並行して開始され時間を節約しますが、両方のプロミスが解決されるまでユーザーはレンダリングされた結果を目にすることはありません。 +データを並行でフェッチするためには、データを使用するコンポーネントの外部でリクエストを事前に定義することでリクエストを先行して開始できます。これにより、リクエストを並行で開始して時間を節約できます。ただし、両方のプロミスが解決されるまでレンダリング結果は表示されません。 -下の例では、`getArtist`と`getAlbums`関数が`Page`コンポーネントの外側に定義され、コンポーネント内で`Promise.all`を使用して開始されます: +以下の例では、`getArtist`と`getAlbums`関数は`Page`コンポーネントの外で定義され、`Promise.all`を使用してコンポーネント内で開始されます。 @@ -571,14 +577,15 @@ async function getAlbums(username: string) { } export default async function Page({ - params: { username }, + params, }: { params: Promise<{ username: string }> }) { + const { username } = await params const artistData = getArtist(username) const albumsData = getAlbums(username) - // 両方のリクエストを並行して開始する + // 両方のリクエストを並行で開始 const [artist, albums] = await Promise.all([artistData, albumsData]) return ( @@ -606,11 +613,12 @@ async function getAlbums(username) { return res.json() } -export default async function Page({ params: { username } }) { +export default async function Page({ params }) { + const { username } = await params const artistData = getArtist(username) const albumsData = getAlbums(username) - // 両方のリクエストを並行して開始する + // 両方のリクエストを並行で開始 const [artist, albums] = await Promise.all([artistData, albumsData]) return ( @@ -625,13 +633,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つの方法として、ユーティリティ関数を作成してブロッキングリクエストの上で意図的に呼び出すことによって、*プリロード*パターンを使用することです。たとえば、`checkIsAvailable()`が``のレンダリングをブロックしますが、`preload()`をその前に呼び出すことで``のデータ依存関係を意図的に開始できます。``がレンダリングされるときにはそのデータがすでにフェッチされている状態になります。 -なお、`preload`関数は`checkIsAvailable()`の実行をブロックしません。 +注意すべき点は、`preload`関数が`checkIsAvailable()`の実行を妨げないということです。 @@ -640,7 +648,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 +665,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) } @@ -677,13 +685,14 @@ export default async function Item({ id }) { import Item, { preload, checkIsAvailable } from '@/components/Item' export default async function Page({ - params: { id }, + params, }: { params: Promise<{ id: string }> }) { + const { id } = await params // アイテムデータの読み込みを開始 preload(id) - // 他の非同期タスクを実行 + // 別の非同期タスクを実行 const isAvailable = await checkIsAvailable() return isAvailable ? : null @@ -696,10 +705,11 @@ export default async function Page({ ```jsx title="app/item/[id]/page.js" switcher import Item, { preload, checkIsAvailable } from '@/components/Item' -export default async function Page({ params: { id } }) { +export default async function Page({ params }) { + const { id } = await params // アイテムデータの読み込みを開始 preload(id) - // 他の非同期タスクを実行 + // 別の非同期タスクを実行 const isAvailable = await checkIsAvailable() return isAvailable ? : null @@ -709,11 +719,11 @@ export default async function Page({ params: { id } }) { -> **Good to know:** "preload"関数はAPIではなくパターンであるため、任意の名前を持つことができます。 +> **覚えておくと良いこと:** "preload"関数はAPIではなくパターンであるため、任意の名前を持つことができます。 -#### Reactの`cache`と`server-only`を使用したPreloadパターン {#using-react-cache-and-server-only-with-the-preload-pattern} +#### React `cache`および`server-only`とPreloadパターンの使用 {#using-react-cache-and-server-only-with-the-preload-pattern} -`cache`関数、preloadパターン、`server-only`パッケージを組み合わせて、アプリ全体で使用可能なデータ取得ユーティリティを作成することができます。 +`cache`関数、`preload`パターンと`server-only`パッケージを組み合わせることで、アプリ全体で利用できるデータ取得ユーティリティを作成できます。 @@ -750,19 +760,19 @@ 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`のエクスポートは、Layouts、Pages、その他のコンポーネントで使用でき、いつアイテムのデータを取得するかの制御を提供します。 -> **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} +### クライアントに機密データが露出しないようにする {#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`に設定します: +アプリケーションでのタイントの有効化は、Next.jsのConfigオプション`experimental.taint`を`true`に設定することで行います。 ```js title="next.config.js" module.exports = { @@ -772,7 +782,7 @@ module.exports = { } ``` -次に、`experimental_taintObjectReference`または`experimental_taintUniqueValue`関数に渡したいオブジェクトまたは値を渡します: +その後、`experimental_taintObjectReference`または`experimental_taintUniqueValue`関数にタイントしたいオブジェクトや値を渡します。 @@ -787,11 +797,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 +822,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 +847,8 @@ export async function Page() { const userData = getUserData() return ( ) } @@ -854,8 +864,8 @@ export async function Page() { const userData = await getUserData() return ( ) } diff --git a/docs/01-app/02-building-your-application/02-data-fetching/03-server-actions-and-mutations.mdx b/docs/01-app/02-building-your-application/02-data-fetching/03-server-actions-and-mutations.mdx index a9987446..c6b3e365 100644 --- a/docs/01-app/02-building-your-application/02-data-fetching/03-server-actions-and-mutations.mdx +++ b/docs/01-app/02-building-your-application/02-data-fetching/03-server-actions-and-mutations.mdx @@ -1,24 +1,24 @@ --- -title: 'Server Actions とデータ変更' -nav_title: 'Server Actions とデータ変更' -description: 'Next.jsを用いたフォーム送信とデータ変更の処理方法を学びましょう。' +title: 'Server Actions and Mutations' +nav_title: 'Server Actions and Mutations' +description: 'Next.js でのフォーム送信とデータ変異の処理方法を学びましょう。' related: - description: 'Next.jsにおけるServer Actionsの設定方法を学びましょう' + description: 'Next.jsでサーバーアクションの設定方法を学びましょう' links: - app/api-reference/config/next-config-js/serverActions --- -[Server Actions](https://react.dev/reference/rsc/server-actions) は **非同期関数** であり、サーバー上で実行されます。これらはServerおよびClient Componentsの中で、Next.jsアプリケーションでのフォーム送信とデータの変更を管理するために呼び出すことができます。 +[Server Actions](https://react.dev/reference/rsc/server-actions)は、**非同期関数**で、サーバー上で実行されます。これらは、Next.jsアプリケーションでのフォーム送信およびデータ変異を処理するために、ServerとClient Componentで呼び出すことができます。 -> **🎥 視聴:** Server Actions を用いたデータ変更について詳しく学びましょう → [YouTube (10 分)](https://youtu.be/dDpZfOQBMaU?si=cJZHlUu_jFhCzHUg)。 +> **🎥 視聴:** サーバーアクションを使った変異についてもっと知りましょう → [YouTube (10分)](https://youtu.be/dDpZfOQBMaU?si=cJZHlUu_jFhCzHUg)。 ## 規約 {#convention} -Server Action はReactの[`"use server"`](https://react.dev/reference/react/use-server)ディレクティブを用いて定義できます。非同期関数の上部にディレクティブを置いて、関数をServer Actionとしてマークするか、別ファイルの上部にディレクティブを置いて、そのファイルのすべてのエクスポートをServer Actionとしてマークすることができます。 +Server Actionは、Reactの[`"use server"`](https://react.dev/reference/react/use-server)ディレクティブを使用して定義できます。このディレクティブを`async`関数の上に配置してその関数をServer Actionとしてマークするか、または別のファイルの上に配置してそのファイルのすべてのエクスポートをServer Actionsとしてマークすることができます。 ### Server Components {#server-components} -Server Components は、インライン関数レベルまたはモジュールレベルで`"use server"`ディレクティブを使用できます。Server Actionをインラインで使うには、関数本体の上部に`"use server"`を追加してください: +Server Componentは、インライン関数レベルまたはモジュールレベルの`"use server"`ディレクティブを使用できます。Server Actionをインライン化するには、関数本体の上に`"use server"`を追加してください: @@ -28,7 +28,7 @@ export default function Page() { // Server Action async function create() { 'use server' - // データを変更する + // データを変異させる } return '...' @@ -43,7 +43,7 @@ export default function Page() { // Server Action async function create() { 'use server' - // データを変更する + // データを変異させる } return '...' @@ -55,7 +55,7 @@ export default function Page() { ### Client Components {#client-components} -Client ComponentでServer Actionを呼び出すには、新しいファイルを作成して、その上部に「use server」ディレクティブを追加します。そのファイル内でエクスポートされるすべての関数が、ClientとServer Componentの両方で再利用可能なServer Actionとしてマークされます。 +Client ComponentでServer Actionを呼び出すには、新しいファイルを作成し、その上に`"use server"`ディレクティブを追加してください。ファイル内のすべてのエクスポートされた関数は、ClientとServer Componentの両方で再利用可能なServer Actionsとしてマークされます: @@ -107,9 +107,9 @@ export function Button() { -### アクションを props として渡す {#passing-actions-as-props} +### アクションをpropsとして渡す {#passing-actions-as-props} -Server Action を Client Component に props として渡すこともできます: +Server ActionをClient Componentにpropとして渡すことも可能です: ```jsx @@ -144,29 +144,32 @@ export default function ClientComponent({ updateItemAction }) { -通常、Next.js TypeScriptプラグインは `client-component.tsx` の `updateItemAction` を警告しますが、これは一般にクライアント側とサーバー側の境界を越えてシリアル化できない関数だからです。しかし、`action` として名前付けされた props または `Action` で終了する props は Server Actions を受け取ることが想定されています。これはあくまでヒューリスティックであり、TypeScriptプラグインは実際に Server Action を受け取っているか、通常の関数を受け取っているかはわかりません。ランタイム型チェックにより、間違って関数をClient Componentに渡さないようにします。 - -## 行動 {#behavior} - -- Server actionは、[`
              `要素](#forms) の `action` 属性を使用して呼び出すことができます: - - Server Componentsはデフォルトでプログレッシブエンハンスメントをサポートしており、JavaScriptがまだ読み込まれていない場合や無効になっている場合でもフォームが送信されます。 - - Client Componentsでは、JavaScriptがまだ読み込まれていない場合、Server Actions を呼び出すフォームは送信をキューに入れ、クライアントのハイドレーションを優先します。 - - ハイドレーション後、ブラウザはフォーム送信時にリフレッシュしません。 -- Server Actionsは``に限定されず、イベントハンドラ、`useEffect`、サードパーティのライブラリ、` +
              ) } @@ -259,7 +262,7 @@ export function UserProfile({ userId }) { return (
              - +
              ) } @@ -268,7 +271,7 @@ export function UserProfile({ userId }) {
              -Server Action はフォームデータに加えて `userId` 引数を受け取ります: +Server Actionは、formデータに加えて`userId`引数を受け取ります: @@ -291,20 +294,20 @@ export async function updateUser(userId, formData) {} -> **Good to know**: +> **お役立ち情報**: > -> - 代替として、引数をフォームの隠し入力フィールドとして渡すことができます(例:``)。ただし、その値はレンダリングされたHTMLの一部になり、エンコードされません。 -> - `.bind`はServerとClient Componentsの両方で機能します。それはまた、プログレッシブエンハンスメントをサポートしています。 +> - 代替方法として、引数をフォーム内のhidden inputフィールドとして渡すことができます(例:``)。ただし、値はレンダリングされたHTMLの一部となり、エンコードされません。 +> - `.bind`はServerとClient Componentの両方で機能します。プログレッシブエンハンスメントもサポートしています。 ### ネストされたフォーム要素 {#nested-form-elements} -Server Action を `
              ` 内にネストされた要素、例えば ` +
              ) } @@ -514,7 +517,7 @@ export function Signup() { ```jsx title="app/ui/signup.js" highlight={11,18-20} switcher 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { createUser } from '@/app/actions' const initialState = { @@ -522,15 +525,15 @@ const initialState = { } export function Signup() { - const [state, formAction] = useFormState(createUser, initialState) + const [state, formAction, pending] = useActionState(createUser, initialState) return (
              - + {/* ... */}

              {state?.message}

              - +
              ) } @@ -539,20 +542,16 @@ export function Signup() { -> **Good to know:** -> -> - これらの例は、Next.jsのApp RouterにバンドルされているReactの`useFormState`フックを使用します。React 19を使用している場合は、代わりに`useActionState`を使用してください。詳細は、[Reactドキュメント](https://react.dev/reference/react/useActionState)を参照してください。 +### ペンディング状態 {#pending-states} -### 保留中の状態 {#pending-states} +[`useActionState`](https://react.dev/reference/react/useActionState)フックは、アクションが実行中にローディングインジケーターを表示するために使用できる`pending`ブール値を公開します。 -> - データを変更する前に、ユーザーがアクションを実行するための権限を持っていることを常に確認してください。[認証と認可](#authentication-and-authorization)を参照してください。 - -[`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) フックを使うと、アクションが実行されている間に読み込みインジケーターを表示するために `pending` ブーリアンを利用できます。 +代わりに、[`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus)フックを使用して、アクションが実行中にローディングインジケーターを表示することもできます。このフックを使用する場合、ローディングインジケーターをレンダリングするための別のコンポーネントを作成する必要があります。例えば、アクションが保留中の場合にボタンを無効にするには: -```tsx title="app/submit-button.tsx" highlight={6} switcher +```tsx title="app/ui/button.tsx" highlight={6} switcher 'use client' import { useFormStatus } from 'react-dom' @@ -562,7 +561,7 @@ export function SubmitButton() { return ( ) } @@ -571,7 +570,7 @@ export function SubmitButton() { -```jsx title="app/submit-button.js" highlight={6} switcher +```jsx title="app/ui/button.js" highlight={6} switcher 'use client' import { useFormStatus } from 'react-dom' @@ -581,7 +580,7 @@ export function SubmitButton() { return ( ) } @@ -590,14 +589,50 @@ export function SubmitButton() { -> **Good to know:** -> -> - React 19では、`useFormStatus`は返されるオブジェクトに、データ、メソッド、アクションのようにさらに多くのキーを含みます。React 19を使用していない場合、`pending`キーのみが利用可能です。 -> - React 19では、`useActionState`も返される状態に`pending`キーを含んでいます。 +その後、`SubmitButton`コンポーネントをフォーム内にネストすることができます: + + + + +```tsx title="app/ui/signup.tsx" switcher +import { SubmitButton } from './button' +import { createUser } from '@/app/actions' + +export function Signup() { + return ( +
              + {/* その他のフォーム要素 */} + + + ) +} +``` -### 楽観的な更新 {#optimistic-updates} +
              + -Reactの[`useOptimistic`](https://react.dev/reference/react/useOptimistic)フックを使用して、Server Actionの実行が完了する前にUIを楽観的に更新し、レスポンスを待つことなく更新することができます: +```jsx title="app/ui/signup.js" switcher +import { SubmitButton } from './button' +import { createUser } from '@/app/actions' + +export function Signup() { + return ( +
              + {/* その他のフォーム要素 */} + + + ) +} +``` + +
              +
              + +> **お役立ち情報:** React 19では、`useFormStatus`には返されたオブジェクトのデータ、メソッド、アクションのような追加のキーが含まれます。React 19を使用していない場合は、`pending`キーのみが利用可能です。 + +### 楽観的更新 {#optimistic-updates} + +Reactの[`useOptimistic`](https://react.dev/reference/react/useOptimistic)フックを使用して、Server Actionが実行を完了する前にUIを楽観的に更新することができます: @@ -618,7 +653,7 @@ export function Thread({ messages }: { messages: Message[] }) { string >(messages, (state, newMessage) => [...state, { message: newMessage }]) - const formAction = async (formData) => { + const formAction = async (formData: FormData) => { const message = formData.get('message') as string addOptimisticMessage(message) await send(message) @@ -631,7 +666,7 @@ export function Thread({ messages }: { messages: Message[] }) { ))}
              - +
              ) @@ -666,7 +701,7 @@ export function Thread({ messages }) { ))}
              - +
              ) @@ -678,7 +713,7 @@ export function Thread({ messages }) { ### イベントハンドラ {#event-handlers} -Server Actions を `
              ` 要素内で使用するのが一般的ですが、`onClick` などのイベントハンドラーで呼び出すこともできます。たとえば、いいね数を増やす場合: +ほとんどの場合、Server Actionsは``要素内で使用されますが、`onClick`のようなイベントハンドラを使用して呼び出すこともできます。例えば、いいねの数を増やす場合: @@ -694,14 +729,14 @@ export default function LikeButton({ initialLikes }: { initialLikes: number }) { return ( <> -

              Total Likes: {likes}

              +

              総いいね数: {likes}

              ) @@ -722,14 +757,14 @@ export default function LikeButton({ initialLikes }) { return ( <> -

              Total Likes: {likes}

              +

              総いいね数: {likes}

              ) @@ -739,7 +774,7 @@ export default function LikeButton({ initialLikes }) {
              -以下のようにフォーム要素にもイベントハンドラーを追加できます: +フォーム要素にイベントハンドラを追加することも可能です。例えば、`onChange`でフィールドを保存する場合: ```tsx title="app/ui/edit-post.tsx" 'use client' @@ -755,17 +790,17 @@ export default function EditPost() { await saveDraft(e.target.value) }} /> - +
              ) } ``` -このような場合には、不要なServer Actionの呼び出しを防ぐために**デバウンス処理**をお勧めします。 +このような場合、複数のイベントが短期間に連続して発生する可能性があるので、不要なServer Actionsの呼び出しを防ぐために**デバウンス**をお勧めします。 ### `useEffect` {#useeffect} -Reactの[`useEffect`](https://react.dev/reference/react/useEffect)フックを使って、コンポーネントがマウントされたときや依存関係が変更されたときにServer Actionを呼び出すことができます。これは、グローバルイベントに依存する変更や自動的にトリガーされる必要のある変更に便利です。たとえば、アプリのショートカット用の`onKeyDown`、無限スクロールの交差オブザーバーフック、または表示回数を更新するために、コンポーネントがマウントされたときに実行されるなど: +Reactの[`useEffect`](https://react.dev/reference/react/useEffect)フックを使用して、コンポーネントのマウント時や依存関係が変更されたときにServer Actionを呼び出すことができます。これは、グローバルイベントに依存する変更や自動的にトリガーする必要がある変更に役立ちます。例えば、アプリのショートカットに対して`onKeyDown`を使用する場合や、無限スクロールのためのインタクション観測フック、あるいはコンポーネントのマウント時にビューのカウントを更新する場合: @@ -788,7 +823,7 @@ export default function ViewCount({ initialViews }: { initialViews: number }) { updateViews() }, []) - return

              Total Views: {views}

              + return

              総ビュー数: {views}

              } ``` @@ -813,26 +848,26 @@ export default function ViewCount({ initialViews }: { initialViews: number }) { updateViews() }, []) - return

              Total Views: {views}

              + return

              総ビュー数: {views}

              } ```
              -`useEffect`の[振る舞いと注意点](https://react.dev/reference/react/useEffect#caveats)を忘れずに考慮してください。 +`useEffect`の[動作と注意点](https://react.dev/reference/react/useEffect#caveats)を検討することを忘れないでください。 ### エラーハンドリング {#error-handling} -エラーがスローされると、クライアント側で最も近い `error.js` または `` バウンダリによってキャッチされます。詳しくは[エラーハンドリング](/docs/app/building-your-application/routing/error-handling)を参照してください。 +エラーがスローされると、それはクライアント上の最も近い`error.js`または``境界でキャッチされます。[エラーハンドリング](/docs/app/building-your-application/routing/error-handling)についての詳細を参照してください。 -> **Good to know:** +> **お役立ち情報:** > -> - エラーをスローする以外に、オブジェクトを `useFormState` で処理するために返すこともできます。[サーバーサイドの検証とエラーハンドリング](#server-side-form-validation)を参照してください。 +> - エラーをスローする以外にも、`useActionState`で処理できるオブジェクトを返すこともできます。[サーバーサイドの検証とエラーハンドリング](#server-side-form-validation)を参照してください。 ### データの再検証 {#revalidating-data} -`revalidatePath` APIを使ってServer Actions内でNext.jsキャッシュを再検証することができます: +Next.jsのキャッシュで`revalidatePath` APIを使用してServer Actions内でデータを再検証することができます:[Next.js Cache](/docs/app/building-your-application/caching): @@ -875,7 +910,7 @@ export async function createPost() { -または、特定のデータフェッチをキャッシュタグで無効化するには、`revalidateTag` APIを使用してください: +または、キャッシュタグを使用して特定のデータフェッチを無効化することもできます。[`revalidateTag`](/docs/app/api-reference/functions/revalidateTag): @@ -920,7 +955,7 @@ export async function createPost() { ### リダイレクト {#redirecting} -Server Action の完了後にユーザーを別のルートにリダイレクトさせたい場合は、`redirect` APIを使用できます。`redirect`は`try/catch`ブロックの外側で呼ばれる必要があります: +Server Actionの完了後にユーザーを異なるルートにリダイレクトしたい場合は、[`redirect`](/docs/app/api-reference/functions/redirect) APIを使用できます。`redirect`は`try/catch`ブロックの外で呼び出す必要があります: @@ -939,7 +974,7 @@ export async function createPost(id: string) { } revalidateTag('posts') // キャッシュされた投稿を更新する - redirect(`/post/${id}`) // 新しいポストページに移動 + redirect(`/post/${id}`) // 新しい投稿ページにナビゲートする } ``` @@ -960,7 +995,7 @@ export async function createPost(id) { } revalidateTag('posts') // キャッシュされた投稿を更新する - redirect(`/post/${id}`) // 新しいポストページに移動 + redirect(`/post/${id}`) // 新しい投稿ページにナビゲートする } ``` @@ -969,7 +1004,7 @@ export async function createPost(id) { ### Cookie {#cookies} -`cookies` APIを使って、Server Action内でCookieを取得、設定、および削除できます: +Server Action内で`cookies` APIを使用して、cookieを`get`, `set`, および`delete`することができます: @@ -1019,42 +1054,40 @@ export async function exampleAction() { -サーバーアクションからCookieを削除するための[追加の例](/docs/app/api-reference/functions/cookies#deleting-cookies)を参照してください。 +Server Actionsからのcookieの削除については[追加の例](/docs/app/api-reference/functions/cookies#deleting-cookies)を参照してください。 ## セキュリティ {#security} -デフォルトでは、Server Actionが作成されてエクスポートされると、パブリックなHTTPエンドポイントが作成され、 -それに伴うセキュリティ仮説と認可チェックが組み込まれます。つまり、サーバーのアクションまたはユーティリティ関数があなたのコードの他の場所でインポートされていなくても、それはまだパブリックにアクセス可能です。 +デフォルトでは、Server Actionが作成されてエクスポートされると、公開されたHTTPエンドポイントとして機能し、同じセキュリティ仮定と認可チェックで扱うべきです。これは、Server Actionやユーティリティ関数がコードの他のどこにもインポートされなくても、公開されたアクセスポイントとなります。 -セキュリティを向上させるため、Next.jsには次の組み込み機能があります: +セキュリティを向上させるために、Next.jsには次の組み込み機能があります: -- **セキュアなアクションID:** Next.jsはクライアントがServer Actionを参照し呼び出すための暗号化された非同期IDを作成します。 - これらのIDは、強化されたセキュリティのためにビルド間で定期的に再計算されます。 -- **デッドコードの除去:** そのIDによって参照される未使用のServer Actionsは、サードパーティによるパブリックアクセスを避けるために - クライアントバンドルから除去されます。 +- **セキュアなアクションID:** Next.jsは暗号化されかつ非決定論的なIDを作成し、クライアントがServer Actionを参照して呼び出すことを可能にします。これらのIDは、セキュリティを高めるためにビルド間で定期的に再計算されます。 +- **デッドコードの削除:** クライアントバンドルからアクセス防止するためにServer Actionの未使用(IDで参照されている)が除去されます。 -> **Good to know**: +> **お役立ち情報**: > -> IDはコンパイル中に作成され、最長14日間キャッシュされます。それらは新しいビルドが開始されるたび、またはビルドキャッシュが無効になったときに再生成されます。このセキュリティの向上は、認証レイヤーが欠けている場合のリスクを低減します。ただし、あなたはServer ActionsをパブリックなHTTPエンドポイントのように取り扱う必要があります。 +> IDはコンパイル中に作成され、最大14日間キャッシュされます。それらは新しいビルドが開始されるか、ビルドキャッシュが無効化されると再生成されます。 +> このセキュリティの向上は、認証レイヤーが欠如している場合のリスクを低減します。ただし、Server Actionsは公開されたHTTPエンドポイントのように扱うべきです。 ```jsx // app/actions.js 'use server' -// このアクションはアプリケーションで使用されているため、Next.jsは -// クライアントがServer Actionを参照し呼び出すことを可能にするための -// セキュアなIDを作成します。 +// このアクションはアプリケーションで使用されていますので、Next.js +// はクライアントがServer Actionを参照して呼び出すための +// セキュアIDを作成します。 export async function updateUserAction(formData) {} -// このアクションは私たちのアプリケーションで使用されていないため、Next.js -// は自動でビルド中にこのコードを削除し、パブリックなエンドポイントを -// 作成しません。 +// このアクションはアプリケーションで使用されていないので、Next.js +// は自動的にこのコードを`next build`中に削除し、 +// 公開されたエンドポイントを作成しません。 export async function deleteUserAction(formData) {} ``` ### 認証と認可 {#authentication-and-authorization} -ユーザーがアクションを実行する権限があることを確認する必要があります。例えば: +ユーザーがアクションを実行する権限を持っていることを確認する必要があります。例えば: ```tsx title="app/actions.ts" 'use server' @@ -1073,7 +1106,7 @@ export function addItem() { ### クロージャと暗号化 {#closures-and-encryption} -コンポーネント内でServer Actionを定義すると、アクションが外部関数のスコープにアクセスできる[クロージャ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)を作成します。たとえば、`publish`アクションは`publishVersion`変数にアクセスできます: +コンポーネント内でServer Actionを定義すると、そのアクションは外部関数のスコープへのアクセスを持つ[クロージャ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)を作成します。例えば、`publish`アクションは`publishVersion`変数にアクセスできます: @@ -1085,14 +1118,14 @@ export default async function Page() { async function publish() { "use server"; if (publishVersion !== await getLatestVersion()) { - throw new Error('公開ボタンを押してからバージョンが変更されました。'); + throw new Error('公開をクリックしてからバージョンが変更されました'); } ... } return (
              - +
              ); } @@ -1108,14 +1141,14 @@ export default async function Page() { async function publish() { "use server"; if (publishVersion !== await getLatestVersion()) { - throw new Error('公開ボタンを押してからバージョンが変更されました。'); + throw new Error('公開をクリックしてからバージョンが変更されました'); } ... } return (
              - +
              ); } @@ -1124,32 +1157,31 @@ export default async function Page() {
              -クロージャは特にレンダリング時点のデータの*スナップショット*(例えば`publishVersion`)をキャプチャして、後でアクションが呼び出されたときに使用するために便利です。 +クロージャは、アクションが呼び出されたときに使用できるように、レンダリング時にデータ(例:`publishVersion`)のスナップショットをキャプチャする必要がある場合に役立ちます。 -しかし、これが行われるためには、キャプチャされた変数はアクションが呼び出されたときクライアントに送信され、サーバーに送り返されることになります。機密データがクライアントに公開されないようにするため、Next.jsは自動的にクロージャされた変数を暗号化します。各アクションには、新しいプライベートキーがNext.jsアプリケーションがビルドされるたびに生成されます。これは、特定のビルドに対してのみアクションが呼び出されうることを意味します。 +ただし、これを行うには、キャプチャされた変数がクライアントに送信され、アクションが呼び出されたときにサーバーに戻されます。センシティブなデータがクライアントに公開されるのを防ぐために、Next.jsは自動的にクロールド変数を暗号化します。新しい秘密鍵は、Next.jsアプリケーションがビルドされるたびに、各アクションごとに生成されます。つまり、そのアクションは特定のビルドでのみ呼び出すことができます。 -> **Good to know:** 機密値がクライアントに公開されないようにするために、暗号化だけに依存することはお勧めしません。代わりに、[React taint API](/docs/app/building-your-application/data-fetching/fetching#preventing-sensitive-data-from-being-exposed-to-the-client)を使用して、特定のデータがクライアントに送信されるのを積極的に防ぐようにしてください。 +> **お役立ち情報:** センシティブな値がクライアントに公開されるのを防ぐために、暗号化に単独で頼ることはお勧めしません。代わりに、[React taint API](/docs/app/building-your-application/data-fetching/fetching#preventing-sensitive-data-from-being-exposed-to-the-client)を使用して、クライアントに送信される特定のデータを積極的に防ぐことをお勧めします。 -### 暗号化キーの上書き(上級){#overwriting-encryption-keys-advanced} +### 暗号化キーの上書き(上級) {#overwriting-encryption-keys-advanced} -複数のサーバーにまたがってNext.jsアプリケーションをセルフホスティングする場合、各サーバーインスタンスが異なる暗号化キーを持つ可能性があり、その結果一貫性のない動作が発生する可能性があります。 +複数のサーバーでNext.jsアプリケーションをセルフホスティングする場合、それぞれのサーバーインスタンスが異なる暗号化キーを持つ可能性があり、不整合を引き起こすことがあります。 -これを防ぐには、`process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY`環境変数を使って暗号化キーを上書きすることができます。この変数を指定することで、暗号化キーの持続性がビルド間で保証され、すべてのサーバーインスタンスが同じキーを使用するようになります。 +これを緩和するために`process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY`環境変数を使用して暗号化キーを上書きすることができます。この変数を指定することで暗号化キーがビルド間で永続化され、すべてのサーバーインスタンスが同じキーを使用するようになります。 -これは、あなたのアプリケーションにとって複数のデプロイにわたって一貫した暗号化の動作が重要である場合は上級のユースケースです。キーのローテーションや署名といった標準的なセキュリティプラクティスも考慮すべきです。 +これは、複数のデプロイメントにわたる暗号化動作がアプリケーションにとって重要である場合の高度なユースケースです。キーのローテーションや署名など通常のセキュリティプラクティスを考慮する必要があります。 -> **Good to know:** VercelにデプロイされたNext.jsアプリケーションは自動的にこれを処理します。 +> **お役立ち情報:** VercelにデプロイされたNext.jsアプリケーションは自動的にこれを処理します。 -### 許可されたオリジン(上級){#allowed-origins-advanced} +### 許可されたオリジン(上級) {#allowed-origins-advanced} -Server Actionsは`
              `要素内で呼び出せるため、[CSRF攻撃](https://developer.mozilla.org/en-US/docs/Glossary/CSRF)にさらされることになります。 +Server Actionsは``要素内で呼び出されることができるため、[CSRF攻撃](https://developer.mozilla.org/en-US/docs/Glossary/CSRF)にさらされることがあります。 -Server Actionsは`POST`メソッドを使用し、これがそれらを呼び出せる唯一のHTTPメソッドです。これによりモダンなブラウザでCSRFの脆弱性のほとんどが防止され、特に[SameSite Cookie](https://web.dev/articles/samesite-cookies-explained)がデフォルトで有効です。 +Server Actionsの裏では`POST`メソッドが使用されており、このHTTPメソッドのみがそれらを呼び出すことができます。これにより、[SameSite cookie](https://web.dev/articles/samesite-cookies-explained)がデフォルトである現代のブラウザにおける大半のCSRFの脆弱性を防ぐようになっています。 -追加の保護として、Next.jsのServer Actionsは`Origin`ヘッダーと`Host`ヘッダー(または`X-Forwarded-Host`)を比較します。これらが一致しない場合、リクエストは中断されます。つまり、Server Actionsはそれをホストしているページと同じホストでのみ呼び出すことができます。 +追加の保護として、Next.jsのServer Actionsは[Originヘッダー](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)と[Hostヘッダー](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host)(または`X-Forwarded-Host`)を比較します。これらが一致しない場合、リクエストは中止されます。つまり、Server Actionsはそれをホストするページと同じホスト上でのみ呼び出されることができます。 -リバースプロキシや多段階バックエンドアーキテクチャを使用する大規模なアプリケーション(サーバーAPIが本番環境のドメインと異なる場合)では、設定オプションとして -`serverActions.allowedOrigins` オプションを使用して安全なオリジンのリストを指定することをお勧めします。このオプションは文字列の配列を受け入れます。 +リバースプロキシやマルチレイヤーのバックエンドアーキテクチャを使用する大規模なアプリケーション(サーバーAPIがプロダクションドメインと異なる場合)においては、設定オプション[`serverActions.allowedOrigins`](/docs/app/api-reference/config/next-config-js/serverActions)を使用して安全なオリジンのリストを指定することをお勧めします。このオプションは文字列の配列を受け入れます。 ```js title="next.config.js" /** @type {import('next').NextConfig} */ @@ -1162,11 +1194,11 @@ module.exports = { } ``` -[セキュリティとServer Actions](https://nextjs.org/blog/security-nextjs-server-components-actions)についてさらに詳しく学びましょう。 +[セキュリティとServer Actions](https://nextjs.org/blog/security-nextjs-server-components-actions)についてもっと詳しく知ることができます。 -## 追加資料 {#additional-resources} +## 追加のリソース {#additional-resources} -詳細については、以下のReactドキュメントを参照してください: +詳細については、以下のReactのドキュメントを参照してください: - [Server Actions](https://react.dev/reference/rsc/server-actions) - [`"use server"`](https://react.dev/reference/react/use-server) 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 73684ad5..d095c246 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,6 +1,6 @@ --- -title: 'Incremental Static Regeneration (ISR)' -description: 'Incremental Static Regenerationを使用して、実行時に静的ページを作成または更新する方法を学びます。' +title: 'インクリメンタル スタティック リジェネレーション (ISR)' +description: 'インクリメンタル スタティック リジェネレーションを使用して、実行時に静的ページを作成または更新する方法を学びましょう。' ---
              @@ -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秒に1回キャッシュを無効化します。 export const revalidate = 60 -// ビルド時には`generateStaticParams`によるパラメータのみをプリレンダリングします。 -// ランダムなリクエストがまだ生成されていないパスの場合、 -// Next.jsはそのページを要求時にサーバーレンダリングします。 -export const dynamicParams = true // またはfalseにして未確認パスで404を表示 +// ビルド時に `generateStaticParams` からのパラメータのみをプリレンダリングします。 +// まだ生成されていないパスに対してリクエストが来た場合、 +// Next.js はオンデマンドでページをサーバーレンダリングします。 +export const dynamicParams = true // 未知のパスなら404にするためにfalseにする 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秒に1回キャッシュを無効化します。 export const revalidate = 60 -// ビルド時には`generateStaticParams`によるパラメータのみをプリレンダリングします。 -// ランダムなリクエストがまだ生成されていないパスの場合、 -// Next.jsはそのページを要求時にサーバーレンダリングします。 -export const dynamicParams = true // またはfalseにして未確認パスで404を表示 +// ビルド時に `generateStaticParams` からのパラメータのみをプリレンダリングします。 +// まだ生成されていないパスに対してリクエストが来た場合、 +// Next.js はオンデマンドでページをサーバーレンダリングします。 +export const dynamicParams = true // 未知のパスなら404にするためにfalseにする 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,9 @@ export const getStaticPaths: GetStaticPaths = async () => { params: { id: String(post.id) }, })) - // ビルド時にのみこれらのパスをプリレンダリングします。 - // { fallback: 'blocking' }はパスが存在しない場合に - // サーバーがページを要求時にレンダリングします。 + // ビルド時にこれらのパスのみをプリレンダリングします。 + // { fallback: 'blocking' } はパスが存在しない場合に + // オンデマンドでページをサーバレンダリングします。 return { paths, fallback: false } } @@ -147,8 +153,8 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はリクエストが到着したときに、 + // 多くても60秒に1回キャッシュを無効化します。 revalidate: 60, } } @@ -175,8 +181,8 @@ export async function getStaticPaths() { params: { id: post.id }, })) - // ビルド時にのみこれらのパスをプリレンダリングします。 - // { fallback: false }は他のルートが404であるべきことを意味します。 + // ビルド時にこれらのパスのみをプリレンダリングします。 + // { fallback: false } は他のルートが404であるべきであることを意味します。 return { paths, fallback: false } } @@ -187,8 +193,8 @@ export async function getStaticProps({ params }) { return { props: { post }, - // リクエストが来た際、Next.jsはキャッシュを無効化し、 - // 最大60秒ごとに一度だけ更新します。 + // Next.js はリクエストが到着したときに、 + // 多くても60秒に1回キャッシュを無効化します。 revalidate: 60, } } @@ -208,16 +214,16 @@ 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} @@ -226,7 +232,7 @@ export default function Page({ post }) { - [`revalidate`](/docs/app/api-reference/file-conventions/route-segment-config#revalidate) - [`dynamicParams`](/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams) -### 関数 {#functions} +### Functions {#functions} - [`revalidatePath`](/docs/app/api-reference/functions/revalidatePath) - [`revalidateTag`](/docs/app/api-reference/functions/revalidateTag) @@ -235,7 +241,7 @@ export default function Page({ post }) { -### 関数 {#functions} +### Functions {#functions} - [`getStaticProps`](https://nextjs.org/docs/canary/pages/building-your-application/data-fetching/get-static-props) - [`res.revalidate`](https://nextjs.org/docs/canary/pages/building-your-application/routing/api-routes#response-helpers) @@ -246,9 +252,9 @@ export default function Page({ post }) { -### 時間に基づく再検証 {#time-based-revalidation} +### 時間ベースの再検証 {#time-based-revalidation} -これは`/blog`にブログ投稿のリストを表示します。1時間後、このページのキャッシュは次の訪問で無効化されます。そして、バックグラウンドで新しいバージョンのページが最新のブログ投稿を伴って生成されます。 +この機能は `/blog` でブログ投稿のリストを取得して表示します。1時間後、このページのキャッシュは次回の訪問時に無効化されます。そして、バックグラウンドで、新しいブログ投稿でページの最新バージョンが生成されます。 @@ -260,7 +266,7 @@ interface Post { content: string } -export const revalidate = 3600 // 毎時間無効化 +export const revalidate = 3600 // 1時間ごとに無効化 export default async function Page() { const data = await fetch('https://api.vercel.app/blog') @@ -282,7 +288,7 @@ export default async function Page() { ```jsx title="app/blog/page.js" switcher -export const revalidate = 3600 // 毎時間無効化 +export const revalidate = 3600 // 1時間ごとに無効化 export default async function Page() { const data = await fetch('https://api.vercel.app/blog') @@ -303,13 +309,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 +326,7 @@ export default async function Page() { import { revalidatePath } from 'next/cache' export async function createPost() { - // キャッシュ内の/postsルートを無効化 + // キャッシュ内の /posts ルートを無効化します revalidatePath('/posts') } ``` @@ -334,7 +340,7 @@ export async function createPost() { import { revalidatePath } from 'next/cache' export async function createPost() { - // キャッシュ内の/postsルートを無効化 + // キャッシュ内の /posts ルートを無効化します revalidatePath('/posts') } ``` @@ -342,11 +348,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 +383,7 @@ export default async function Page() { -ORMを使用している場合やデータベースに接続している場合は、`unstable_cache`を使用できます: +ORM を使用している場合やデータベースに接続している場合は、`unstable_cache` を使用できます: @@ -424,7 +430,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 +441,7 @@ export default async function Page() { import { revalidateTag } from 'next/cache' export async function createPost() { - // キャッシュ内の'tags'でタグ付けされた - // すべてのデータを無効化 + // キャッシュ内の 'posts' とタグ付けされたすべてのデータを無効化します revalidateTag('posts') } ``` @@ -450,8 +455,7 @@ export async function createPost() { import { revalidateTag } from 'next/cache' export async function createPost() { - // キャッシュ内の'tags'でタグ付けされた - // すべてのデータを無効化 + // キャッシュ内の 'posts' とタグ付けされたすべてのデータを無効化します revalidateTag('posts') } ``` @@ -463,11 +467,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 Route は、`/api/revalidate?secret=` で呼び出して、指定されたブログ投稿を再検証できます。Next.js アプリのみが知っているシークレットトークンを作成します。このシークレットは、再検証 API Route への不正アクセスを防止するために使用されます。 @@ -479,19 +483,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 +506,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 +527,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 +564,23 @@ 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秒に1回キャッシュを無効化します。 revalidate: 60, } } @@ -586,22 +591,23 @@ 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秒に1回キャッシュを無効化します。 revalidate: 60, } } @@ -614,17 +620,17 @@ export async function getStaticProps({ params }) { ### キャッシュの保存場所をカスタマイズする {#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 サーバーのファイルシステム(ディスク上)に保存されます。セルフホスティングを行う際、Pages と 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 +642,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 ランタイム(デフォルト)を使用している場合にのみサポートされています。 +- [スタティック エクスポート](/docs/app/building-your-application/deploying/static-exports)を作成する際には、ISR はサポートされていません。 +- 静的にレンダリングされたルートに複数の `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 ランタイム(デフォルト)を使用している場合にのみサポートされています。 +- [スタティック エクスポート](/docs/app/building-your-application/deploying/static-exports)を作成する際には、ISR はサポートされていません。 +- オンデマンド 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: [ボット対応 ISR フォールバック](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 1a376b76..e08b41a4 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) +- [Static Rendering](#static-rendering-default) +- [Dynamic Rendering](#dynamic-rendering) +- [Streaming](#streaming) -このページでは、Server Components がどのように機能するか、いつ使用するか、異なるサーバーレンダリング戦略について説明します。 +このページでは、Server Componentsがどのように機能するのか、どのような場面で使用するのか、そして異なるサーバーレンダリング戦略について説明します。 ## サーバーレンダリングの利点 {#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 Componentsを使用すると、データ取得をサーバー側に移動させ、データソースに近づけることができます。これにより、レンダリングに必要なデータを取得するための時間が短縮され、クライアントが行うリクエストの数が減少し、パフォーマンスが向上します。 +- **セキュリティ**:Server Componentsを使用することで、トークンやAPIキーなどの機密データやロジックをサーバー側に保持し、クライアントに露出するリスクを避けることができます。 +- **キャッシュ**:サーバーでレンダリングすることで、その結果をキャッシュし、後続のリクエストや他のユーザーでも再利用することができます。これにより、各リクエスト時に行うレンダリングやデータ取得の量が減少し、パフォーマンスが向上し、コストが削減されます。 +- **パフォーマンス**:Server Componentsは、パフォーマンスの最適化のための追加ツールを提供します。例えば、完全にClient Componentsで構成されたアプリから始めた場合、UIの対話性のない部分をServer Componentsに移行すると、クライアント側のJavaScriptの量を減らすことができます。これは、遅いインターネットやパワーの少ないデバイスを使用しているユーザーにとって有益です。ブラウザはダウンロード、パース、実行するクライアント側のJavaScriptの量が少なくて済むからです。 +- **初回ページロードと[First Contentful Paint (FCP)](https://web.dev/fcp/)**:サーバーサイドでHTMLを生成し、クライアントがページをレンダリングするために必要なJavaScriptをダウンロード、パース、実行するのを待つことなく、ユーザーに即座にページを表示することができます。 +- **検索エンジン最適化とソーシャルネットワーク共有**:レンダリングされたHTMLは、検索エンジンボットによってページをインデックス化したり、ソーシャルカードプレビューを生成したりするために使用できます。 +- **ストリーミング**:Server Componentsを使用すると、レンダリング作業をチャンクに分割し、それらを準備が整い次第クライアントにストリーミングすることができます。これにより、ページ全体がサーバーでレンダリングされるのを待たずに、ページの一部を早く見ることができます。 -## Next.jsでの Server Components の使用 {#using-server-components-in-next-js} +## Next.jsでのServer Componentsの使用 {#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 Componentsを使用します。これにより、追加の設定なしでサーバーレンダリングを自動的に実装できますが、必要に応じてClient Componentsを使用することができます。詳細は[Client Components](/docs/app/building-your-application/rendering/client-components)を参照してください。 -## Server Components はどのようにレンダリングされますか? {#how-are-server-components-rendered} +## Server Componentsのレンダリング方法 {#how-are-server-components-rendered} -サーバー上で、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントと[サスペンス境界](https://react.dev/reference/react/Suspense)によってチャンクに分割されます。 +サーバー側では、Next.jsはReactのAPIを使ってレンダリングを調整します。レンダリング作業は、個々のルートセグメントと[サスペンス境界](https://react.dev/reference/react/Suspense)によりチャンクに分割されます。 各チャンクは2つのステップでレンダリングされます: -1. Reactは Server Components を**React Server Component Payload (RSC Payload)**という特別なデータ形式にレンダリングします。 -2. Next.jsはRSC Payloadと Client Components のJavaScript命令を使用して、サーバー上で**HTML**をレンダリングします。 +1. Reactはサーバーコンポーネントを**React Server Component Payload (RSC Payload)**と呼ばれる特別なデータ形式にレンダリングします。 +2. Next.jsはRSC PayloadとClient Componentsの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 Components Payloadがクライアントとサーバーコンポーネントのツリーを調整し、DOMを更新するために使用されます。 +3. JavaScript命令が使用され、クライアントコンポーネントが[ハイドレーション](https://react.dev/reference/react-dom/client/hydrateRoot)され、アプリケーションが対話的になります。 > #### 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 +> - サーバーコンポーネントのレンダリング結果 +> - クライアントコンポーネントがレンダリングされるべき場所のプレースホルダーとそれらのJavaScriptファイルへの参照 +> - サーバーコンポーネントからクライアントコンポーネントに渡されるプロップ ## サーバーレンダリング戦略 {#server-rendering-strategies} -サーバーレンダリングには3つのサブセットがあります:静的、動的、ストリーミングです。 +サーバーレンダリングには、Static、Dynamic、Streamingの3つのサブセットがあります。 -### 静的レンダリング(デフォルト) {#static-rendering-default} +### Static Rendering (デフォルト) {#static-rendering-default} -静的レンダリングでは、ルートは**ビルド時**または[データの再検証](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)後にバックグラウンドでレンダリングされます。その結果はキャッシュされ、[コンテンツデリバリーネットワーク (CDN)](https://developer.mozilla.org/docs/Glossary/CDN)にプッシュすることができます。この最適化により、レンダリング作業の結果をユーザー間やサーバーリクエスト間で共有できます。 +Static Renderingでは、ルートは**ビルド時**または[データの再検証](/docs/app/building-your-application/data-fetching/incremental-static-regeneration)後にバックグラウンドでレンダリングされます。結果はキャッシュされ、[コンテンツ配信ネットワーク (CDN)](https://developer.mozilla.org/docs/Glossary/CDN)にプッシュすることができます。この最適化により、ユーザーやサーバーのリクエスト間でレンダリング作業の結果を共有できます。 -静的レンダリングは、ルートがユーザーにパーソナライズされておらず、ビルド時に知っていることができるデータを持つ場合に有用です。例えば静的なブログ記事や商品ページなどです。 +Static renderingは、ブログ記事や商品ページのように、ユーザーにパーソナライズされないデータがある場合や、ビルド時に知り得るデータがある場合に有用です。 -### 動的レンダリング {#dynamic-rendering} +### Dynamic Rendering {#dynamic-rendering} -動的レンダリングでは、ルートは各ユーザーに対して**リクエスト時**にレンダリングされます。 +Dynamic Renderingでは、ルートはユーザーごとに**リクエスト時**にレンダリングされます。 -動的レンダリングは、ルートがユーザーにパーソナライズされたデータを持つ場合や、キャッシュされていないデータがリクエスト時にしか知られない場合に有用です。たとえば、クッキーやURLの検索パラメーターです。 +Dynamic renderingは、ユーザーにパーソナライズされたデータがある場合や、リクエスト時にしか知り得ない情報(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)や`{ cache: 'no-store' }`の[fetch](/docs/app/api-reference/functions/fetch)オプションが発見された場合、Next.jsは全体のルートをダイナミックにレンダリングするように切り替えます。この表は、Dynamic APIとデータキャッシュがルートが静的または動的にレンダリングされるかどうかに与える影響をまとめたものです: -| 動的API | データ | ルート | -| ------- | ------------ | ---------------- | -| なし | キャッシュ | 静的レンダリング | -| あり | キャッシュ | 動的レンダリング | -| なし | 非キャッシュ | 動的レンダリング | -| あり | 非キャッシュ | 動的レンダリング | +| Dynamic APIs | Data | Route | +| ------------ | ---------- | -------------------- | +| No | Cached | Statically Rendered | +| Yes | Cached | Dynamically Rendered | +| No | Not Cached | Dynamically Rendered | +| Yes | Not Cached | Dynamically Rendered | -上の表では、ルートが完全に静的であるためには、すべてのデータがキャッシュされていなければなりません。しかし、キャッシュされたデータ取得とキャッシュされていない取得の両方を使用した動的にレンダリングされたルートを持つことができます。 +上記の表では、完全に静的なルートにするには、すべてのデータをキャッシュする必要があります。しかし、キャッシュされたデータフェッチとキャッシュされていないデータフェッチの両方を使用する、動的にレンダリングされたルートを持つことができます。 -開発者として、静的と動的レンダリングのどちらを選ぶ必要はありません。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) @@ -106,26 +106,26 @@ React Server Componentsを使用すると、UIをサーバーでレンダリン - [`searchParams` prop](/docs/app/api-reference/file-conventions/page#searchparams-optional) - [`unstable_noStore`](/docs/app/api-reference/functions/unstable_noStore) -### ストリーミング {#streaming} +### Streaming {#streaming} ストリーミング中にルートセグメントを並列化する図。データ取得、レンダリング、および個々のチャンクのハイドレーションを示しています。 -ストリーミングを使用すると、サーバーから段階的にUIをレンダリングできます。作業はチャンクに分割され、準備が整うとクライアントにストリーム配信されます。これにより、全体のコンテンツが完全にレンダリングされる前に、ユーザーが直ちにページの一部を表示できるようになります。 +Streamingを使用すると、サーバー側からUIを段階的にレンダリングすることができます。作業はチャンクに分割され、それらが準備ができ次第クライアントにストリームされます。これにより、ページ全体のコンテンツがレンダリングを完了する前に、ユーザーが即座にページの一部を見ることができます。 クライアント上で部分的にレンダリングされたページを示す図。ストリーミングされているチャンクのためのローディングUI。 -ストリーミングは、デフォルトでNext.js App Routerに組み込まれています。これにより、初期ページロードのパフォーマンス向上が図られると同時に、遅いデータ取得に依存してルート全体のレンダリングをブロックするUIも改善します。たとえば、商品のレビューなどです。 +Streamingはデフォルトで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/03-rendering/03-composition-patterns.mdx b/docs/01-app/02-building-your-application/03-rendering/03-composition-patterns.mdx index a65f61cf..686a23ef 100644 --- a/docs/01-app/02-building-your-application/03-rendering/03-composition-patterns.mdx +++ b/docs/01-app/02-building-your-application/03-rendering/03-composition-patterns.mdx @@ -1,46 +1,46 @@ --- -title: 'ServerとClientの構成パターン' -nav_title: '構成パターン' -description: 'ServerとClient Componentsを使用する際の推奨されるパターン。' +title: 'サーバーとクライアントのコンポジションパターン' +nav_title: 'コンポジションパターン' +description: 'Server ComponentとClient Componentを使用するための推奨パターン。' --- -Reactアプリケーションを構築するとき、アプリケーションのどの部分をサーバーでレンダリングするか、またはクライアントでレンダリングするかを検討する必要があります。このページでは、ServerとClient Componentsを使用する際の推奨される構成パターンを紹介します。 +Reactアプリケーションを構築する際に、どの部分をサーバーでレンダリングするべきか、クライアントでレンダリングするべきかを考慮する必要があります。このページでは、Server ComponentとClient Componentを使用する際の推奨されるコンポジションパターンについて説明します。 -## ServerとClient Componentsを使うべき状況は? {#when-to-use-server-and-client-components} +## Server ComponentとClient Componentをいつ使用するか? {#when-to-use-server-and-client-components} -以下は、ServerとClient Componentsを使用するための異なるユースケースの簡単なまとめです: +Server ComponentとClient Componentのさまざまなユースケースを簡単にまとめたものです。 -| 何をする必要がありますか? | Server Component | Client Component | -| --------------------------------------------------------------------------------------- | ------------------- | ------------------- | -| データを取得する | | | -| バックエンドリソースに直接アクセスする | | | -| センシティブな情報をサーバーに保持する(アクセストークン、APIキーなど) | | | -| 大きな依存をサーバーに保持する / クライアントサイドのJavaScriptを削減する | | | -| インタラクティブ性とイベントリスナーを追加する(`onClick()`、`onChange()`など) | | | -| 状態とライフサイクルの効果を使用する(`useState()`、`useReducer()`、`useEffect()`など) | | | -| ブラウザー限定APIを使用する | | | -| 状態、効果、またはブラウザー限定APIに依存するカスタムフックを使用する | | | -| [React Class components](https://react.dev/reference/react/Component)を使用する | | | +| 何をする必要がありますか? | Server Component | Client Component | +| ------------------------------------------------------------------------------------------- | ------------------- | ------------------- | +| データを取得する | | | +| バックエンドリソースに直接アクセスする | | | +| 機密情報(アクセストークンやAPIキーなど)をサーバーに保持する | | | +| 大きな依存関係をサーバーに保持する / クライアントサイドのJavaScriptを削減する | | | +| 双方向機能やイベントリスナー(`onClick()`、`onChange()`など)を追加する | | | +| 状態やライフサイクルエフェクト(`useState()`、`useReducer()`、`useEffect()`など)を使用する | | | +| ブラウザ専用APIを使用する | | | +| 状態、エフェクト、またはブラウザ専用APIに依存するカスタムフックを使用する | | | +| [React Class components](https://react.dev/reference/react/Component)を使用する | | | -## Server Componentパターン {#server-component-patterns} +## Server Componentのパターン {#server-component-patterns} -クライアントサイドのレンダリングを選択する前に、データの取得やデータベースやバックエンドサービスへのアクセスなど、一部の作業をサーバーで行うことを検討するかもしれません。 +クライアントサイドレンダリングを選択する前に、サーバーで行う作業を検討する場合があります。例えば、データの取得やデータベースやバックエンドサービスへのアクセスなどです。 -以下は、Server Componentsを扱う際の一般的なパターンです: +以下は、Server Componentを使用する際の一般的なパターンです。 ### コンポーネント間でデータを共有する {#sharing-data-between-components} -サーバーでデータを取得する場合、異なるコンポーネント間でデータを共有する必要があるケースがあるかもしれません。例えば、同じデータに依存するレイアウトとページがあるかもしれません。 +サーバーでデータを取得する場合、異なるコンポーネント間でデータを共有する必要があることがあります。たとえば、同じデータに依存するレイアウトとページがある場合です。 -[React Context](https://react.dev/learn/passing-data-deeply-with-context)(サーバー上では利用不可)を使用したり、データをpropsとして渡したりする代わりに、`fetch`やReactの`cache`関数を使用して、必要なコンポーネントで同じデータを取得できます。同じデータに対して重複したリクエストを気にすることなく、Reactは`fetch`を拡張し、データリクエストを自動的にメモ化します。また、`fetch`が利用できない場合には`cache`関数を使用できます。 +[React Context](https://react.dev/learn/passing-data-deeply-with-context)(サーバーでは利用できません)を使用したり、propsとしてデータを渡す代わりに、`fetch`やReactの`cache`関数を使用して必要なコンポーネント内で同じデータを取得できます。この方法は、同じデータに対して重複したリクエストが発生する心配がありません。これは、Reactが`fetch`を拡張してデータリクエストを自動的にメモ化するためです。`fetch`が利用できない場合は、`cache`関数を使用できます。 -[このパターンの例を表示](/docs/app/building-your-application/data-fetching/fetching#reusing-data-across-multiple-functions)。 +[このパターンの例を参照](/docs/app/building-your-application/data-fetching/fetching#reusing-data-across-multiple-functions)してください。 -### Server専用コードをクライアント環境から排除する {#keeping-server-only-code-out-of-the-client-environment} +### サーバー専用コードをクライアント環境から排除する {#keeping-server-only-code-out-of-the-client-environment} -JavaScriptモジュールはServerとClientの両方のComponentで共有されることがあるため、サーバーでのみ実行することを想定していたコードがクライアントに入り込む可能性があります。 +JavaScriptモジュールはServer ComponentとClient Componentの両方で共有できるため、サーバーでのみ実行するつもりのコードがクライアントに持ち込まれる可能性があります。 -例えば、次のようなデータ取得関数を考えてみましょう: +たとえば、次のデータ取得関数を考えてみましょう。 @@ -75,21 +75,21 @@ export async function getData() { -一見すると、`getData`はサーバーとクライアントの両方で動作するように見えます。しかし、この関数はサーバーでのみ実行されることを意図して書かれており、`API_KEY`を含んでいます。 +一見すると、`getData`はサーバーとクライアントの両方で動作するように見えます。しかし、この関数にはサーバーでのみ実行することを前提に書かれた`API_KEY`が含まれています。 -環境変数`API_KEY`が`NEXT_PUBLIC`で始まっていないため、これはプライベートな変数であり、サーバー上でのみアクセス可能です。Next.jsはプライベート環境変数をクライアントに漏れるのを防ぐため、空の文字列で置き換えます。 +環境変数`API_KEY`は`NEXT_PUBLIC`で始まっていないため、サーバーでのみアクセスできるプライベート変数です。環境変数がクライアントに漏れるのを防ぐため、Next.jsはプライベート環境変数を空の文字列に置き換えます。 -その結果、`getData()`はクライアントでインポートして実行できますが、期待どおりに動作しません。変数を公開すればクライアントで関数が動作するようになりますが、センシティブな情報をクライアントに公開したくないかもしれません。 +その結果、`getData()`をクライアントでインポートして実行することは可能ですが、期待どおりに動作しません。また、変数を公開すればクライアントで関数が動作するようになってしまいますが、機密情報をクライアントに公開したくない場合もあるでしょう。 -サーバーコードの意図しないクライアントでの使用を防ぐために、`server-only`パッケージを使用して、これらのモジュールがClient Componentに誤ってインポートされた場合に他の開発者にビルド時のエラーを出すことができます。 +このようなサーバーコードの意図しないクライアント使用を防ぐために、`server-only`パッケージを使用して、これらのモジュールをClient Componentに誤ってインポートした場合にビルド時エラーを発生させることができます。 -`server-only`を使用するためには、まずパッケージをインストールします: +`server-only`を使用するには、まずパッケージをインストールします。 ```bash title="Terminal" npm install server-only ``` -その後、サーバー専用のコードを含むモジュールにパッケージをインポートします: +その後、サーバー専用コードを含むモジュールにパッケージをインポートします。 ```js title="lib/data.js" import 'server-only' @@ -105,19 +105,19 @@ export async function getData() { } ``` -これで、`getData()`をインポートしたClient Componentは、ビルド時にこのモジュールはサーバーでのみ使用可能であるというエラーを受け取ることになります。 +これで、`getData()`をインポートする任意のClient Componentは、このモジュールはサーバーでのみ使用可能であることを説明するビルド時エラーを受け取ります。 -対応するパッケージ`client-only`は、`window`オブジェクトにアクセスするコードなど、クライアント専用コードを含むモジュールをマークするために使用できます。 +対応するパッケージの`client-only`を使用して、クライアント専用コードを含むモジュールをマークできます。たとえば、`window`オブジェクトにアクセスするコードです。 -### サードパーティパッケージやプロバイダーを使用する {#using-third-party-packages-and-providers} +### サードパーティパッケージとプロバイダを使用する {#using-third-party-packages-and-providers} -Server Componentsは新しいReactの機能であるため、エコシステムのサードパーティのパッケージとプロバイダーは、「use client」ディレクティブをクライアント専用の機能(`useState`、`useEffect`、`createContext`など)を使用するコンポーネントに追加し始めています。 +Server ComponentはReactの新機能であるため、エコシステム内のサードパーティパッケージおよびプロバイダは現在、クライアント専用機能(`useState`、`useEffect`、および`createContext`など)を使用しているコンポーネントに`"use client"`ディレクティブを追加し始めています。 -今日、多くの`npm`パッケージのクライアント専用機能を使用するコンポーネントは、まだディレクティブを持っていません。これらのサードパーティのコンポーネントは、`"use client"`ディレクティブを持つClient Components内で使うと期待どおり動作しますが、Server Components内では動作しません。 +現在、`npm`パッケージからの多くのクライアント専用機能を使用しているコンポーネントにはまだこのディレクティブがありません。これらのサードパーティのコンポーネントはClient Component内で期待通りに動作しますが、Server Component内では動作しません。 -例えば、仮の`acme-carousel`パッケージをインストールし、``というコンポーネントがあるとしましょう。このコンポーネントは`useState`を使用しますが、まだ`"use client"`ディレクティブを持っていません。 +たとえば、クライアント専用機能を使用している``コンポーネントを持つ架空の`acme-carousel`パッケージをインストールしたとします。このコンポーネントは`useState`を使用しますが、まだ`"use client"`ディレクティブがありません。 -もし``をClient Component内で使用すると、期待どおり動作します: +``をClient Component内で使用すると、期待どおりに動作します。 @@ -168,7 +168,7 @@ export default function Gallery() { -しかし、Server Component内で直接使用しようとすると、エラーが表示されます: +ただし、Server Component内で直接使用しようとすると、エラーが表示されます。 @@ -209,9 +209,9 @@ export default function Page() { -これはNext.jsが``がクライアント専用の機能を使用していることを知らないためです。 +これは、Next.jsが``がクライアント専用機能を使用していることを知らないためです。 -これを修正するために、クライアント専用の機能に依存するサードパーティコンポーネントを自分のClient Componentsでラップすることができます: +これを解決するには、クライアント専用機能に依存するサードパーティのコンポーネントを自己のClient Componentでラップできます。 @@ -238,7 +238,7 @@ export default Carousel -これで、Server Component内で直接``を使用することができます: +これで、をServer Component内で直接使用できます。 @@ -279,11 +279,11 @@ export default function Page() { -私たちは、ほとんどのサードパーティコンポーネントをラップする必要はないと考えています。なぜなら、それらをClient Components内で使用することが多いためです。しかし、例外はプロバイダーです。プロバイダーはReactの状態とコンテキストに依存しており、典型的にはアプリケーションのrootで必要とされるためです。[以下でサードパーティのコンテキストプロバイダーについて詳しく学びましょう](#using-context-providers)。 +ほとんどのサードパーティコンポーネントをラップする必要はないと期待しています。なぜなら、通常、Client Components内で使用すると思われるからです。ただし、プロバイダは例外です。これらは通常、Reactの状態とコンテキストに依存し、アプリケーションのルートで必要とされます。 [サードパーティのコンテキストプロバイダについて詳しく学ぶ](#using-context-providers)。 -#### コンテキストプロバイダーの使用 {#using-context-providers} +#### コンテキストプロバイダを使用する {#using-context-providers} -コンテキストプロバイダーは通常、アプリケーションのroot付近でレンダリングされ、現在のテーマなどのグローバルな問題を共有します。[React コンテキスト](https://react.dev/learn/passing-data-deeply-with-context)はServer Componentsではサポートされていないため、アプリケーションのrootでコンテキストを作成しようとするとエラーが発生します: +コンテキストプロバイダは、通常、現在のテーマなどのグローバル問題を共有するためにアプリケーションのルート近くにレンダリングされます。 [Reactコンテキスト](https://react.dev/learn/passing-data-deeply-with-context)はServer Componentではサポートされていないため、アプリケーションのルートでコンテキストを作成しようとするとエラーが発生します。 @@ -294,7 +294,11 @@ import { createContext } from 'react' // createContext is not supported in Server Components export const ThemeContext = createContext({}) -export default function RootLayout({ children }) { +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { return ( @@ -328,7 +332,7 @@ export default function RootLayout({ children }) { -これを解決するためには、コンテキストを作成し、そのプロバイダーをClient Component内にレンダリングします: +これを修正するには、コンテキストを作成し、そのプロバイダをClient Component内でレンダリングします。 @@ -367,7 +371,7 @@ export default function ThemeProvider({ children }) { -Server ComponentはプロバイダーがClient Componentとしてマークされたので、直接レンダリングできます: +Server Componentは、Client Componentとしてマークされたプロバイダを直接レンダリングできます。 @@ -410,38 +414,38 @@ export default function RootLayout({ children }) { -プロバイダーがrootにレンダリングされることで、アプリ全体の他のClient Componentsは、このコンテキストを利用できます。 +プロバイダをルートにレンダリングすることで、アプリ内の他のすべてのClient Componentがこのコンテキストを消費できます。 -> **Good to know**: プロバイダーはできるだけ深い位置にレンダリングするべきです。 `ThemeProvider`が、HTMLドキュメント全体ではなく `{children}` のみをラップしている点に注目してください。これにより、Next.jsはServer Componentsの静的な部分を最適化しやすくなります。 +> **Good to know**: プロバイダはできるだけtreeの奥深くにレンダリングするべきです。`ThemeProvider`が`{children}`をwrapしていて、``ドキュメント全体をwrapしていないことに注意してください。これにより、Next.jsがServer Componentの静的な部分を最適化しやすくなります。 -#### ライブラリアー作者へのアドバイス {#advice-for-library-authors} +### ライブラリアーサーへのアドバイス {#advice-for-library-authors} -同様に、他の開発者に消費されるパッケージを作成しているライブラリアー作者は、パッケージのクライアントエントリーポイントをマークするために`"use client"`ディレクティブを使用できます。これにより、パッケージユーザーはServer Componentsにパッケージコンポーネントを直接インポートし、ラッピング境界を作成する必要がなくなります。 +同様に、他の開発者が消費するパッケージを作成するライブラリアーサは、パッケージのクライアントエントリポイントをマークするために`"use client"`ディレクティブを使用できます。これにより、パッケージユーザーはラップバウンダリを作成せずに、Server Componentにパッケージコンポーネントを直接インポートできます。 -モジュールをServer Componentのモジュールグラフの一部に含めることを可能にするためには、['use client' をツリーの深い場所で使用して](#moving-client-components-down-the-tree)、パッケージを最適化できます。 +パッケージを最適化するために、[`"use client"`をtreeの詳細を指定すると](#moving-client-components-down-the-tree)、インポートされたモジュールがServer Componentのモジュールグラフの一部になるようにします。 -一部のバンドラは`"use client"`ディレクティブを削除することがあります。`React Wrap Balancer`や`Vercel Analytics`リポジトリで[esbuildを設定する例](https://github.com/shuding/react-wrap-balancer/blob/main/tsup.config.ts#L10-L13)を見つけることができます。 +一部のバンドラは`"use client"`ディレクティブを取り除くことがあることに注意してください。`React Wrap Balancer`と`Vercel Analytics`リポジトリで `"use client"` 指令を含めるようにesbuildを構成する例を確認できます。 -## Client Components {#client-components} +## Client Component {#client-components} -### Client Componentsをツリーの深い場所に移動する {#moving-client-components-down-the-tree} +### クライアントコンポーネントをツリーの下に移動する {#moving-client-components-down-the-tree} -Client JavaScriptのバンドルサイズを削減するため、Client Componentsをコンポーネントツリーの下位に移動することをお勧めします。 +クライアントJavaScriptバンドルサイズを削減するために、Client Componentをコンポーネントツリーの下に移動することをお勧めします。 -例えば、静的な要素(ロゴ、リンクなど)とstateを使用するインタラクティブな検索バーを含むレイアウトがあるかもしれません。 +たとえば、レイアウトには静的要素(例: ロゴ、リンクなど)があり、状態を使用するインタラクティブな検索バーがあることがあります。 -レイアウト全体をClient Componentにする代わりに、インタラクティブなロジックをClient Component(例:``)に移動し、レイアウトをServer Componentとして保持します。これにより、レイアウトのすべてのコンポーネントJavaScriptをクライアントに送信する必要がなくなります。 +レイアウト全体をClient Componentにするのではなく、インタラクティブなロジックをClient Component(例: ``)に移動し、レイアウトをServer Componentとして保持します。これにより、レイアウトのすべてのコンポーネントJavaScriptをクライアントに送信する必要がなくなります。 ```tsx title="app/layout.tsx" switcher -// SearchBar is a Client Component +// SearchBarはClient Componentです import SearchBar from './searchbar' -// Logo is a Server Component +// LogoはServer Componentです import Logo from './logo' -// Layout is a Server Component by default +// LayoutはデフォルトでServer Componentです export default function Layout({ children }: { children: React.ReactNode }) { return ( <> @@ -459,12 +463,12 @@ export default function Layout({ children }: { children: React.ReactNode }) { ```jsx title="app/layout.js" switcher -// SearchBar is a Client Component +// SearchBarはClient Componentです import SearchBar from './searchbar' -// Logo is a Server Component +// LogoはServer Componentです import Logo from './logo' -// Layout is a Server Component by default +// LayoutはデフォルトでServer Componentです export default function Layout({ children }) { return ( <> @@ -481,38 +485,39 @@ export default function Layout({ children }) { -### ServerからClient Componentsにpropsを渡す(シリアライズ) {#passing-props-from-server-to-client-components-serialization} +### ServerからClient Componentsへのpropsの渡し(シリアル化) {#passing-props-from-server-to-client-components-serialization} -Server Componentでデータを取得した場合、それをClient Componentにpropsとして渡すことを望むかもしれません。ServerからClient Componentsに渡されるpropsはReactによって[シリアライズ可能](https://react.dev/reference/react/use-server#serializable-parameters-and-return-values)である必要があります。 +Server Componentでデータを取得した場合、そのデータをClient Componentにpropsとして渡したいことがあります。ServerからClient Componentに渡されるpropsはReactによって[シリアライズ可能](https://react.dev/reference/react/use-server#serializable-parameters-and-return-values)である必要があります。 -Client Componentsがシリアライズできないデータに依存している場合は、[サードパーティライブラリを使用してクライアントでデータを取得](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-client)するか、[Route Handler](https://nextjs.org/docs/app/building-your-application/routing/route-handlers)を使用してサーバーでデータを取得することができます。 +Client Componentがシリアライズできないデータに依存する場合、[サードパーティライブラリを使用してクライアントでデータを取得する](/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-client)か、[Route Handler](/docs/app/building-your-application/routing/route-handlers)でサーバー上でデータを取得することができます。 -## ServerとClient Componentsのインターレース {#interleaving-server-and-client-components} +## ServerとClient Componentsの織り交ぜ {#interleaving-server-and-client-components} -Client ComponentsとServer Componentsを交互に使用する際には、UIをコンポーネントのツリーとして視覚化すると役立つ場合があります。[root レイアウト](https://nextjs.org/docs/app/building-your-application/routing/layouts-and-templates#root-layout-required)はServer Componentで始まり、その後`"use client"`ディレクティブを追加することで、クライアント上で特定のコンポーネントサブツリーをレンダリングすることができます。 +Client ComponentとServer Componentを織り交ぜる際に、UIをコンポーネントのtreeとして視覚化することが役立ちます。 [rootレイアウト](/docs/app/building-your-application/routing/layouts-and-templates#root-layout-required)、これはServer Componentです、から始めて、 `"use client"`ディレクティブを追加することで、クライアント上でコンポーネントの特定のsubtreeをレンダリングすることができます。 -{/* Diagram - interleaving */} +{/* 図:織り交ぜ */} -これらのクライアントサブツリー内では、依然としてServer Componentsをネストしたり、Server Actionsを呼び出したりすることは可能ですが、考慮すべき点があります。 +そのクライアントのsubtree内に、依然としてServer ComponentをネストしたりServer Actionsを呼び出すことができますが、いくつか注意点があります。 -- リクエスト-レスポンスライフサイクル中に、コードはサーバーからクライアントに移動します。クライアント上でサーバー上のデータやリソースにアクセスする必要がある場合は、新しいリクエストがサーバーに送られます。切り替えるのではなく、行き来することはありません -- 新しいリクエストがサーバーに送られると、すべてのServer Componentが最初にレンダリングされ、Client Component内にネストされているものも含まれます。レンダリングされた結果([RSCペイロード](https://nextjs.org/docs/app/building-your-application/rendering/server-components#what-is-the-react-server-component-payload-rsc))には、Client Componentsの場所への参照が含まれます。その後、クライアント上でReactはこのRSCペイロードを使ってServerとClient Componentsを統合し、1つのツリーにします +- リクエストとレスポンスのライフサイクル中に、コードはサーバーからクライアントに移動します。クライアント上でサーバーのデータやリソースにアクセスする必要がある場合、新たに**サーバーにリクエスト**をすることになります - サーバーとクライアントを行ったり来たりするのではありません。 +- 新しいリクエストがサーバーに行われると、すべてのServer Componentが最初にレンダリングされます。これにはClient Component内にネストされているものも含まれます。レンダリングの結果([RSC Payload](/docs/app/building-your-application/rendering/server-components#what-is-the-react-server-component-payload-rsc))には、Client Componentの場所への参照が含まれます。その後、クライアント側で、ReactはRSC Payloadを使用してServerとClient Componentsを単一のツリーに精製します。 -{/* Diagram */} +{/* 図 */} -- Client ComponentsはServer Componentsの後にレンダリングされるため、Server ComponentをClient Componentモジュール内にインポートすることはできません(新しいリクエストでサーバーに戻る必要があります)。代わりに、Server ComponentをpropsとしてClient Componentに渡すことができます。[サポートされていないパターン](#unsupported-pattern-importing-server-components-into-client-components)と[サポートされているパターン](#supported-pattern-passing-server-components-to-client-components-as-props)のセクションを参照してください。 +- Client ComponentはServer Componentの後にレンダリングされるため、Client ComponentモジュールにServer Componentをインポートすることはできません(サーバーへの新しいリクエストが必要になるため)。代わりに、Server ComponentをClient Componentに`props`として渡すことができます。次の[非サポートパターン](#unsupported-pattern-importing-server-components-into-client-components)と[サポートパターン](#supported-pattern-passing-server-components-to-client-components-as-props)を参照してください。 -### サポートされていないパターン:Server ComponentsをClient Componentsにインポートする {#unsupported-pattern-importing-server-components-into-client-components} +### サポートされていないパターン: Client ComponentにServer Componentをインポートする {#unsupported-pattern-importing-server-components-into-client-components} -以下のパターンはサポートされていません。Client ComponentにServer Componentをインポートすることはできません: +次のパターンはサポートされていません。Client ComponentにServer Componentをインポートすることはできません。 -```tsx title="app/client-component.tsx" highlight={3,4,17} switcher +```tsx title="app/client-component.tsx" switcher +highlight={3,4,17} 'use client' -// You cannot import a Server Component into a Client Component. +// Client ComponentにServer Componentをインポートすることはできません。 import ServerComponent from './Server-Component' export default function ClientComponent({ @@ -535,10 +540,11 @@ export default function ClientComponent({ -```jsx title="app/client-component.js" highlight={3,13} switcher +```jsx title="app/client-component.js" switcher +highlight={3,13} 'use client' -// You cannot import a Server Component into a Client Component. +// Client ComponentにServer Componentをインポートすることはできません。 import ServerComponent from './Server-Component' export default function ClientComponent({ children }) { @@ -557,18 +563,19 @@ export default function ClientComponent({ children }) { -### サポートされているパターン:Server ComponentsをClient Componentsにpropsとして渡す {#supported-pattern-passing-server-components-to-client-components-as-props} +### サポートされるパターン: Server ComponentをClient Componentにpropsとして渡す {#supported-pattern-passing-server-components-to-client-components-as-props} -以下のパターンはサポートされています。Server ComponentsをpropsとしてClient Componentに渡すことができます。 +以下のパターンはサポートされています。Server ComponentをClient Componentにpropとして渡すことができます。 -一般的なパターンは、`children` propを使用して、Client Componentに*"スロット"*を作成することです。 +一般的なパターンとして、Reactの`children` propを使用してClient Componentに*"スロット"*を作成します。 -以下の例では、``が`children` propを受け入れます: +以下の例では、``は`children` propを受け取ります。 -```tsx title="app/client-component.tsx" highlight={6,15} switcher +```tsx title="app/client-component.tsx" switcher +highlight={6,15} 'use client' import { useState } from 'react' @@ -592,7 +599,8 @@ export default function ClientComponent({ -```jsx title="app/client-component.js" highlight={5,12} switcher +```jsx title="app/client-component.js" switcher +highlight={5,12} 'use client' import { useState } from 'react' @@ -613,21 +621,20 @@ export default function ClientComponent({ children }) { -``は、`children`が最終的にServer Componentの結果で満たされることを知りません。``の唯一の責任は、`children`をどこに配置するかを決定することです。 +``は、`children`が最終的にServer Componentの結果で埋められることを知りません。 ``の唯一の責任は、`children`が最終的にどこに配置されるかを決定することです。 -親Server Componentで、``と``の両方をインポートし、``を``の子として渡すことができます: +親Server Componentでは、``と``の両方をインポートして、``を``の子として渡すことができます。 ```tsx title="app/page.tsx" highlight={11} switcher -// This pattern works: -// You can pass a Server Component as a child or prop of a -// Client Component. +// このパターンは動作します: +// Server ComponentをClient Componentの子またはプロップとして渡すことができます。 import ClientComponent from './client-component' import ServerComponent from './server-component' -// Pages in Next.js are Server Components by default +// Next.jsのページはデフォルトでServer Componentです export default function Page() { return ( @@ -641,13 +648,12 @@ export default function Page() { ```jsx title="app/page.js" highlight={11} switcher -// This pattern works: -// You can pass a Server Component as a child or prop of a -// Client Component. +// このパターンは動作します: +// Server ComponentをClient Componentの子またはプロップとして渡すことができます。 import ClientComponent from './client-component' import ServerComponent from './server-component' -// Pages in Next.js are Server Components by default +// Next.jsのページはデフォルトでServer Componentです export default function Page() { return ( @@ -660,9 +666,9 @@ export default function Page() { -このアプローチでは、``と``は独立してレンダリングされることができ、``はクライアント上の``がレンダリングされる前に、サーバー上でレンダリングされます。 +このアプローチでは、``と``は分離され、独立してレンダリングできます。この場合、子の``は、``がクライアントでレンダリングされるずっと前にサーバー上でレンダリングできます。 > **Good to know:** > -> - 再レンダリングされるときにネストされた子コンポーネントが再レンダリングされないようにするために、"コンテンツを持ち上げる"パターンが使用されてきました -> - `children` propに限定されません。任意のpropを使用してJSXを渡すことができます +> - "コンテンツを持ち上げる"というパターンは、親コンポーネントが再レンダリングされたときにネストされた子コンポーネントを再レンダリングしないために使用されてきました。 +> - `children` propに限定されているわけではありません。JSXを渡すために任意のpropを使用できます。 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 b024cc73..86aa90a6 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,39 +1,39 @@ --- -title: 'Next.jsのキャッシュ' -nav_title: 'キャッシュ' +title: 'Next.jsにおけるキャッシング' +nav_title: 'キャッシング' 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)。 +> **Good to know**: このページは、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は[`fetch` API](#fetch)を拡張して、同じURLとオプションを持つリクエストを自動的に**メモ化**します。これにより、React component treeの複数個所で同じデータに対してfetch関数を呼び出しても、それが一度だけ実行されます。 重複排除されたFetchリクエスト -例えば、ルート全体で同じデータが必要な場合(例えば、Layout、Page、および複数のコンポーネントにおいて)、treeの最上部でデータをfetchし、コンポーネント間でpropsを転送する必要はありません。その代わりに、必要なコンポーネント内でデータを取得でき、同じデータに対するネットワーク上での複数リクエストのパフォーマンスへの影響を心配する必要はありません。 +たとえば、ルート全体で同じデータを使用する必要がある場合(例:Layout、Page、および複数のコンポーネントで)、ツリーの上位でデータを取得し、コンポーネント間でpropsを転送する必要はありません。その代わりに、必要なデータを必要なコンポーネント内で取得し、ネットワークを介して同じデータに対して複数のリクエストを行うことによるパフォーマンスへの影響を心配する必要はありません。 ```tsx title="app/example.tsx" switcher async function getItem() { - // `fetch`関数は自動的にメモ化され、その結果はキャッシュされます + // `fetch` 関数は自動的にメモ化され、その結果がキャッシュされる const res = await fetch('https://.../item/1') return res.json() } -// この関数は2回呼び出されますが、最初の1回のみ実行されます +// この関数は2回呼び出されますが、最初の1回だけ実行されます 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回呼び出されますが、最初の1回だけ実行されます const item = await getItem() // cache MISS -// 二度目の呼び出しはルート内のどこでも可能です +// 2回目の呼び出しはルート内のどこにでもできます const item = await getItem() // cache HIT ``` -**リクエストメモ化の仕組み** +**Request Memoizationの仕組み** Reactレンダリング中にfetchメモ化がどのように機能するかを示すダイアグラム。 -- ルートをレンダリングする際に、特定のリクエストが初めて呼び出されたとき、その結果はメモリに存在せず、キャッシュの`MISS`となります。 -- したがって、関数が実行され、データが外部ソースから取得され、その結果がメモリに格納されます。 -- 同じレンダーパス内でのリクエストの後続の関数呼び出しはキャッシュの`HIT`となり、関数を実行することなくメモリからデータが返されます。 -- ルートがレンダリングされ、レンダリングパスが完了すると、メモリは「リセット」され、すべてのリクエストメモ化エントリがクリアされます。 +- ルートをレンダリングしている間、特定のリクエストが初めて呼び出されたとき、その結果はメモリに存在せず、キャッシュ`MISS`になります。 +- そのため、関数が実行され、外部ソースからデータが取得され、結果はメモリに保存されます。 +- 同じレンダリングパス内の後続のリクエストの関数呼び出しはキャッシュ`HIT`となり、関数を実行せずにメモリからデータが返されます。 +- ルートがレンダリングされ、レンダリングパスが完了すると、メモリは「リセット」され、すべてのrequest memoizationのエントリがクリアされます。 > **Good to know**: > -> - リクエストメモ化はReactの機能であり、Next.jsの機能ではありません。ここでは、他のキャッシングメカニズムとの相互作用を示すために含まれています。 +> - Request memoizationはReactの機能であり、Next.jsの機能ではありません。他のキャッシングメカニズムとどのように相互作用するかを示すためにここに含まれています。 > - メモ化は`fetch`リクエストの`GET`メソッドにのみ適用されます。 -> - メモ化はReact Component treeにのみ適用されます。つまり: +> - メモ化はReact Component treeにのみ適用されます。つまり、次のようになります: > - `generateMetadata`、`generateStaticParams`、Layouts、Pages、およびその他のServer Components内の`fetch`リクエストに適用されます。 -> - Route Handlers内の`fetch`リクエストには適用されません。なぜなら、それらはReact component treeの一部ではないからです。 -> - `fetch`が適さない場合(例:一部のデータベースクライアント、CMSクライアント、GraphQLクライアント)、関数をメモ化するために[Reactの`cache`関数](#react-cache-function)を使用できます。 +> - Route Handler内の`fetch`リクエストには適用されません。これらはReact component treeの一部ではないためです。 +> - `fetch`が適していない場合(例:一部のデータベースクライアント、CMSクライアント、またはGraphQLクライアント)、関数をメモ化するために[React `cache`関数](#react-cache-function)を使用できます。 ### 期間 {#duration} -キャッシュはサーバーリクエストのライフタイムが続く間、つまりReact component treeのレンダリングが完了するまで持続します。 +キャッシュはReact component 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`オプションはサーバー側のリクエストがサーバーのデータキャッシュとどのように相互作用するかを示します。 +> **Good to know**: ブラウザでは、`fetch`の`cache`オプションはリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示します。Next.jsでは、`cache`オプションはサーバーサイドリクエストがサーバーのData Cacheとどのように相互作用するかを示します。 -`fetch`の[`cache`](#fetch-optionscache)および[`next.revalidate`](#fetch-optionsnextrevalidate)オプションを使用して、キャッシング動作を設定できます。 +[`cache`](#fetch-optionscache)および[`next.revalidate`](#fetch-optionsnextrevalidate)の`fetch`オプションを使用してキャッシング動作を設定できます。 -**データキャッシュの仕組み** +**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 renderパス中に同じデータに対して重複リクエストを作成しないようにします。 -> **データキャッシュとリクエストメモ化の違い** +> **Data CacheとRequest Memoizationの違い** > -> 両方のキャッシングメカニズムは、キャッシュされたデータを再利用することによってパフォーマンスを向上させますが、データキャッシュはリクエストとデプロイメントにまたがって永続的に維持されるのに対し、メモ化はリクエストのライフタイム内でのみ持続します。 +> どちらのキャッシングメカニズムもキャッシュされたデータを再利用することでパフォーマンスを向上させますが、Data Cacheは受信リクエストとデプロイメント間で永続する一方で、メモ化はリクエストのライフタイムにのみ続きます。 ### 期間 {#duration} -データキャッシュは、再検証またはオプトアウトが行われない限り、リクエストやデプロイメント間で永続的に保持されます。 +再検証またはオプトアウトしない限り、Data Cacheは受信リクエストとデプロイメント間で持続します。 ### 再検証 {#revalidating} -キャッシュされたデータは次の2つの方法で再検証できます: +キャッシュされたデータは2つの方法で再検証できます: -- **時間ベースの再検証**: 一定時間経過後の新しいリクエストでデータを再検証します。これは、データがあまり頻繁に変化せず、新鮮さがあまり重要でない場合に有用です。 -- **オンデマンドの再検証**: イベントに基づいてデータを再検証します(例:フォーム送信)。オンデマンドの再検証はタグベースまたはパスベースのアプローチを使用してデータのグループを一度に再検証できます。例えば、無頭CMSのコンテンツが更新されたときに最新のデータをすぐに表示したい場合に有効です。 +- **時間ベースの再検証**:ある時間が経過した後に新しいリクエストが行われたとき、データを再検証します。これは、データがめったに変わらず、新鮮さがそれほど重要でない場合に役立ちます。 +- **オンデマンド再検証**:イベントに基づいてデータを再検証します(例:フォーム送信)。オンデマンド再検証は、タグベースやパスベースのアプローチを使用してデータのグループを一度に再検証することができます。これは、ヘッドレスCMSのコンテンツが更新されたときなど、新しいデータをできるだけ早く表示したい場合に役立ちます。 #### 時間ベースの再検証 {#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 boundaryごとに分かれています。 -各チャンクは2つのステップでレンダリングされます: +各チャンクは次の2ステップでレンダリングされます: -1. ReactはServer Componentsをストリーミングに最適化された特別なデータフォーマットにレンダリングします。これは**React Server Component Payload**と呼ばれます。 -2. Next.jsはReact Server Component PayloadとクライアントのJavaScript命令を使用して、サーバー上で**HTML**をレンダリングします。 +1. ReactはReact Server Component Payloadという、ストリーミングに最適化された特別なデータ形式にServer Componentsをレンダリングします。 +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 +> - 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はClientとServer Componentsの対話的ではない初期プレビューをすぐに表示します。 +2. React Server Components Payloadは、ClientおよびレンダリングされたServer Component treeを調整し、DOMを更新します。 +3. JavaScript命令は、Client Componentsを[ハイドレート](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 Component Payloadはクライアント側の[Router Cache](#client-side-router-cache)に保存され、レイアウト、ロード状態、ページごとに分割された別のメモリ内キャッシュとなります。このRouter Cacheは、以前に訪れたルートを保存し、将来のルートをプレフェッチすることでナビゲーション体験を向上させます。 -### 5. 後続のナビゲーション {#5-subsequent-navigations} +### 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} -ルートがビルドタイムにキャッシュされるかどうかは、そのルートが静的または動的にレンダリングされるかどうかに依存します。静的ルートはデフォルトでキャッシュされ、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。 +ルートがビルド時にキャッシュされるかどうかは、そのルートが静的にレンダリングされるか動的にレンダリングされるかに依存します。静的ルートはデフォルトでキャッシュされ、動的ルートはリクエストタイムにレンダリングされ、キャッシュされません。 -以下の図は、静的および動的にレンダリングされたルートの違いを示しており、キャッシュデータと非キャッシュデータが示されています: +この図は、静的および動的にレンダリングされたルートと、キャッシュされたデータとキャッシュされていないデータの違いを示しています: 静的および動的レンダリングがフルルートキャッシュに与える影響を示す図。静的ルートはビルドタイムまたはデータ再検証後にキャッシュされ、動的ルートは決してキャッシュされない。 -[静的および動的レンダリング](/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を再検証すると、サーバーでコンポーネントを再レンダリングして新しいレンダリング出力をキャッシュすることで、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`リクエストは依然としてデータキャッシュにキャッシュされ続けます。これは、キャッシュされたデータとキャッシュされていないデータが共存するハイブリッドを可能にします。 +- **[動的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は訪れたルートセグメントをキャッシュし、ユーザーがナビゲートする可能性の高いルートを[プレフェッチ](/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)を使ってページセグメントをキャッシュすることができます。 +- **レイアウト**はナビゲーションでキャッシュされ、再利用されます([部分的なレンダリング](/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)設定オプションを使用して、ページセグメントのキャッシングを有効にできます。 -{/* TODO: 図をv15の動作に合わせて更新する */} +{/* TODO: v15の動作に合わせて図を更新する */} -> **Good to know:** このキャッシュはNext.jsとServer Componentsに特有であり、ブラウザの[bfcache](https://web.dev/bfcache/)とは異なりますが、似たような結果をもたらします。 +> **Good to know:** このキャッシュは特にNext.jsおよびServer Componentsに適用され、ブラウザの[bfcache](https://web.dev/bfcache/)とは異なりますが、同様の結果をもたらします。 ### 期間 {#duration} -キャッシュはブラウザの一時メモリに格納されます。2つの要因がルーターキャッシュの存続期間を決定します: +キャッシュはブラウザの一時メモリに格納されます。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/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)を使用して上記の自動無効化時間を調整することができます。 +> **Good to know**: 実験的な[`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)を呼び出すことでルーターキャッシュを無効にし、現在のルートに対するサーバーへの新しいリクエストを行う。 +- **サーバーアクション**内で: + - パスごとにオンデマンドでデータを再検証する場合は、([`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 Cacheが無効化され、cookieを使用するルートが古くならないようにします(例:認証)。 +- [`router.refresh`](/docs/app/api-reference/functions/use-router)を呼び出すと、Router Cacheが無効化され、サーバーへの新しいリクエストが現在のルートに対して行われます。 ### オプトアウト {#opting-out} -Next.js 15以降、ページセグメントはデフォルトでオプトアウトされています。 +Next.js 15から、ページセグメントはデフォルトでオプトアウトされています。 -> **Good to know:** ``コンポーネントの`prefetch`プロップを`false`に設定することで、[事前取得](/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)をオプトアウトすることもできます。 +> **Good to know:** ``コンポーネントの`prefetch`プロップを`false`に設定することで、[プレフェッチ](./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はハードリフレッシュまたは自動無効化期間が経過するまで以前のペイロードを提供し続けます。 +- Data CacheとRouter Cacheを即座に無効化するには、[サーバーアクション](/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)におけるData Cacheの再検証は、Router Cacheを直ちに無効化**しません**。Route Handler自体は特定のルートに結び付けられていないためです。したがって、Router Cacheはハードリフレッシュや自動無効化期間が経過するまで、以前のペイロードを提供し続けます。 -## API {#apis} +## APIs {#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からのルートを自動的にプレフェッチし、Router CacheにReact Server Component Payloadを追加します。 -事前取得を無効にするには、`prefetch`プロパティを`false`に設定します。ただし、これはキャッシュを永続的にスキップすることはなく、ユーザーがルートを訪問したときにルートセグメントはクライアント側でキャッシュされます。 +プレフェッチを無効にするには、`prefetch`プロップを`false`に設定できます。ただし、これによりキャッシュが恒久的にスキップされるわけではなく、ユーザーがそのルートにアクセスしたときにルートセグメントはクライアント側にキャッシュされます。 [``コンポーネント](/docs/app/api-reference/components/link)の詳細を学ぶ。 ### `router.prefetch` {#router-prefetch} -`useRouter`フックの`prefetch`プロパティを使用して、ルートを手動で事前取得できます。これにより、Router CacheにReact Server Component Payloadを追加します。 +`useRouter`フックの`prefetch`オプションを使用して、ルートを手動でプレフェッチできます。これにより、React Server Component PayloadがRouter Cacheに追加されます。 -[`useRouter`フック](/docs/app/api-reference/functions/use-router)のAPIリファレンスを参照してください。 +[`useRouter`フック](/docs/app/api-reference/functions/use-router)APIリファレンスを参照してください。 ### `router.refresh` {#router-refresh} -`useRouter`フックの`refresh`プロパティを使用して、ルートを手動で更新できます。これによりRouter Cacheが完全にクリアされ、現在のルートに対するサーバーへの新しいリクエストが行われます。`refresh`はデータキャッシュまたはフルルートキャッシュには影響を与えません。 +`useRouter`フックの`refresh`オプションを使用して、ルートを手動で更新することができます。これにより、Router Cacheが完全にクリアされ、現在のルートに対してサーバーへの新しいリクエストが行われます。`refresh`はData CacheまたはFull Route Cacheには影響しません。 -描画結果はクライアント側で統合され、React状態やブラウザ状態が保持されます。 +レンダリングされた結果はクライアントで調整されながら、React状態とブラウザ状態が維持されます。 -[`useRouter`フック](/docs/app/api-reference/functions/use-router)のAPIリファレンスを参照してください。 +[`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`をキャッシングにオプトインするには、`cache` オプションを`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時間後に再検証 +// 少なくとも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`を使用できる場所が2つあります: -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 Handlerは特定のルートに結び付けられていないため、Router Cacheはすぐには無効になりません。 +2. [サーバーアクション](/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`を使用できる場所が2つあります: -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. [サーバーアクション](/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`** と **`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} -`cookies`や`headers`のような動的API、およびPages内の`searchParams`プロップは実行時のインカミングリクエスト情報に依存します。これらを使用すると、ルートがフルルートキャッシュからオプトアウトし、つまり、ルートが動的にレンダリングされることになります。 +`cookies`や`headers`、そしてPagesの`searchParams`プロップのような動的APIは、ランタイムの受信リクエスト情報に依存しています。これらを使用すると、ルートがFull Route Cacheからオプトアウトします。つまり、そのルートは動的にレンダリングされます。 #### `cookies` {#cookies} -Server Action内で`cookies.set`または`cookies.delete`を使用すると、それを使用するルートが古くならないように、Router Cacheを無効にします(例:認証の変更を反映するため)。 +Server Action内で`cookies.set`または`cookies.delete`を使用すると、cookieを使用するルートが古くならないようにするため(例:認証の変更を反映するため)、Router Cacheが無効化されます。 -[`cookies`](/docs/app/api-reference/functions/cookies) APIリファレンスを参照してください。 +[`cookies`](/docs/app/api-reference/functions/cookies)APIリファレンスをご覧ください。 ### セグメント設定オプション {#segment-config-options} -ルートセグメント設定オプションは、`fetch` APIを使用できない場合(例:データベースクライアントやサードパーティライブラリ)またはデフォルトを上書きする場合に、ルートセグメントの設定をオーバーライドするために使用できます。 +Route Segment Configオプションは、ルートセグメントのデフォルトを上書きするか、`fetch` APIを使用できない場合(例:データベースクライアントやサードパーティライブラリ)に使用できます。 -次のルートセグメント設定オプションはフルルートキャッシュをオプトアウトします: +Full Route Cacheからオプトアウトする以下のRoute Segment Configオプションがあります: - `const dynamic = 'force-dynamic'` -この設定オプションは、すべてのフェッチをデータキャッシュからオプトアウトします(すなわち`no-store`): +この設定オプションは、Data Cacheからすべてのfetchをオプトアウトします(すなわち、`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にキャッシュされます。リクエスト時に、Next.jsはビルド時に知られていなかったパスも、初めて訪れたときにキャッシュします。 -ビルドタイムにすべてのパスを静的にレンダリングするには、`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`から配列を返す必要があります。たとえそれが空でもそうです。さもなければ、ルートは動的にレンダリングされます。 +> **Good to know:** `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`関数を使用すると、関数の戻り値をメモ化することができ、一度しか実行しないにもかかわらず同じ関数を複数回呼び出すことができます。 -`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/05-styling/01-css.mdx b/docs/01-app/02-building-your-application/05-styling/01-css.mdx index b4bebda4..d5c170ef 100644 --- a/docs/01-app/02-building-your-application/05-styling/01-css.mdx +++ b/docs/01-app/02-building-your-application/05-styling/01-css.mdx @@ -1,10 +1,10 @@ --- title: 'CSS' nav_title: 'CSS' -description: 'CSS Modules、グローバルスタイル、外部スタイルシートでNext.jsアプリケーションをスタイリングする。' +description: 'CSS Modules、グローバルスタイル、および外部スタイルシートでNext.jsアプリケーションをスタイリングする。' --- -{/* このドキュメントの内容はapp routerとpages routerで共有されています。Pages Routerに特化したコンテンツを追加するためには、`Content`コンポーネントを使用してください。共有コンテンツはコンポーネントでラップしないでください。 */} +{/* このドキュメントの内容はapp routerとpages router間で共有されます。`PagesOnly>Content`コンポーネントを使用して、Pages Routerに特化したコンテンツを追加できます。共有コンテンツは、コンポーネント内でラップしないでください。 */} @@ -17,7 +17,7 @@ description: 'CSS Modules、グローバルスタイル、外部スタイルシ -Next.jsはCSSを処理するための複数の方法をサポートしています: +Next.jsはいくつかの方法でCSSを処理することをサポートしています: - [CSS Modules](#css-modules) - [グローバルスタイル](#global-styles) @@ -27,12 +27,12 @@ Next.jsはCSSを処理するための複数の方法をサポートしていま Next.jsには、`.module.css`拡張子を使用したCSS Modulesのサポートが組み込まれています。 -CSS Modulesは自動的に一意のクラス名を作成することで、CSSをローカルスコープにします。これにより、異なるファイルで同じクラス名を使用しても、衝突を心配する必要がありません。この動作により、CSS ModulesはコンポーネントレベルのCSSを含めるのに最適な方法となっています。 +CSS Modulesは、ユニークなクラス名を自動的に作成することでCSSをローカルスコープ化します。これにより、異なるファイルで同じクラス名を使用しても、衝突を気にする必要がなくなります。この動作は、CSS ModulesをコンポーネントレベルのCSSを含めるための理想的な方法にしています。 ### 例 {#example} -CSS Modulesは、`app`ディレクトリ内の任意のファイルにインポートできます: +CSS Modulesは`app`ディレクトリ内の任意のファイルにインポートできます: @@ -73,13 +73,13 @@ export default function DashboardLayout({ children }) { -例えば、`components/`フォルダに再利用可能な`Button`コンポーネントを考えてみましょう: +例えば、`components/`フォルダに再利用可能な`Button`コンポーネントがあるとします: -まず、次の内容で`components/Button.module.css`を作成します: +まず、以下の内容で`components/Button.module.css`を作成します: ```css title="Button.module.css" /* -.error {}が他の`.css`や`.module.css`ファイルと衝突する心配はありません! +.error {}が他の`.css`または`.module.css`ファイルと衝突することを心配する必要はありません! */ .error { color: white; @@ -87,7 +87,7 @@ export default function DashboardLayout({ children }) { } ``` -次に、上記のCSSファイルをインポートして使用する`components/Button.js`を作成します: +次に、上記のCSSファイルをインポートし利用する`components/Button.js`を作成します: ```jsx title="components/Button.js" import styles from './Button.module.css' @@ -96,7 +96,8 @@ export function Button() { return (