spinny:~/writing $ less nextjs-16-cache-components.md
12Next.js で長年悩まされてきた質問の 1 つは、「このページは静的ですか、それとも動的ですか?」というものでした。 `cookies()`、さまざまなオプションを備えた `fetch`、データベース クライアント、CMS、ショッピング カート、またはカスタム コンテンツへの呼び出しを追加するまでは、これは単純な質問のように思えます。34Next.js 16 は、この会話の謎を少なくしようとしている点で興味深いです。複雑さが解消されるわけではありませんが、メンタル モデルが変わります。ルートはデフォルトで動的であり、キャッシュは必要に応じて自身を宣言し、`Suspense` は新鮮なままの部分で高速シェルを構成する自然な方法になります。56理解すべき機能はキャッシュ コンポーネントです。安定した Turbopack、React Compiler、`proxy.ts`、および新しい無効化 API は重要ですが、それらは同じ問題、つまりフレームワークが舞台裏で何を決定したかを推測することなく高速アプリを構築することを中心に展開しています。78## このことは重要だから910実際のアプリには、「静的ページ」と「動的ページ」だけが存在するわけではありません。さまざまなニーズを持つさまざまな部品があります。1112商品シートは一日に数回変更される場合がございます。価格はより頻繁に変更される可能性があります。可用性はほぼライブである必要があります。ユーザー名は個人的なものです。レビューはストリーミングできます。サイドバーを安定させることができます。カートにはありません。1314すべてを 1 つの単位として扱うと、常に次の 2 つの極端などちらかになります。1516- 積極的なキャッシュと古いデータが表示されるリスク。17- あらゆる場所で動的レンダリングが行われ、必要以上にパフォーマンスが低下します。1819キャッシュ コンポーネントは、まさにこの誤った選択を回避するために機能します。2021## 実際のモデル2223`cacheComponents: true` を使用すると、`"use cache"` を使用してキャッシュ可能なものを宣言できます。次に、期間とタグを `cacheLife()` および `cacheTag()` に関連付けることができます。動的部分は動的のままであり、`Suspense` を使用して分離できます。2425```mermaid26flowchart TD27 Request[ユーザーリクエスト] --> Shell[キャッシュされたシェル]28 Request --> Dynamic[ダイナミックセクション]29 Shell --> FirstPaint[最初の簡単なコンテンツ]30 Dynamic --> Stream[サスペンス内のストリーミング]31 Stream --> Complete[全ページ]32```3334セットアップは小規模です:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647大きな変更は設定にありません。それはコンポーネントの記述を開始する方法にあります。4849```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';5354async function getProduct(slug: string) {55 'use cache';5657 cacheLife('hours');58 cacheTag(`product:${slug}`);5960 return db.product.findUnique({ where: { slug } });61}6263async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);6566 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}7374async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}7879export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;8182 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```9293ページはすべてキャッシュされている必要も、すべてが動的である必要もありません。製品シートは迅速かつ再利用可能です。在庫は常に新鮮な状態を保つことができます。ユーザーは、最も遅い部分を待たずに、すぐに何かを確認できます。9495## `use cache` は実行可能なドキュメントです9697`"use cache"` について私が気に入っている点は、意図を明示的にするよう強制することです。関数を読むと、誰かが「このデータは再利用できる」と判断したことがすぐにわかります。9899これは、`fetch` を使用していない場合に特に便利です。多くのアプリは、Prisma、Drizzle、内部 SDK、CMS クライアント、またはサービス機能からデータを読み取ります。このような場合、`fetch` オプションのみに基づく従来の推論では十分ではありませんでした。100101経験則:102103- カシェアの内容は比較的安定しています。104- 詳細なタグを使用します。105- 動的な権限、セッション、カート、通知、トランザクション状態を残します。106- 遅い部分を `Suspense` 内に配置します。107- 「パフォーマンスが向上した」と言う前に、測定してください。108109## すべてを捨てずに無効化する110111キャッシュは、正確に更新できる場合にのみ役立ちます。ここで、`cacheTag`、`revalidateTag`、`updateTag` が重要になります。112113例:114115```typescript116'use server';117118import { updateTag } from 'next/cache';119120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125126 updateTag(`product:${productId}`);127}128```129130重要なディテールはタグです。 `product:${productId}` は正確な境界を示します。 `products` は巨大なバケットを示します。巨大なバケツは最初は快適です。数か月後には、タイトルを変更するためにアプリの半分を無効にする理由になります。131132## Stable Turbopack: 毎日耳にする部分133134Next.js 16 では、開発とビルドの中心に Turbopack が組み込まれます。これは最も詩的な機能ではありませんが、作業中に感じるものです。サーバーの起動が早くなり、リフレッシュが速くなり、強制的なコーヒー ブレークのように感じなくなるビルドです。135136とはいえ、カスタム プラグインが満載のコードベースを目をつぶって移行するつもりはありません。私ならチェックします:137138- ローカルビルド。139- 非標準輸入。140- MDX、SVG、CSS。141- Webpack プラグインは残っています。142- 重要なページ。143- ビルド時間の違い。144145新しいプロジェクトの場合は、デフォルトから開始します。成熟したものについては、慎重な移行を行うと思います。146147## React Compiler: 思考ではなくノイズを除去する148149React Compiler 1.0 は安定しており、Next.js 16 は `reactCompiler` でそれをサポートしています。約束は、手動によるメモ化を大幅に減らすことです。つまり、「安全のため」に使用される `memo`、`useMemo`、`useCallback` が減ります。150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162私はそれを魔法の粉のように扱うつもりはありません。コンパイラは、コードが React ルールに適切に準拠している場合に役立ちます。コンポーネントに奇妙な副作用、隠れた突然変異、不適切に使用されたフックがある場合は、まずそれを修正する必要があります。163164健康的に試してみる方法:1651661. `eslint-plugin-react-hooks` を更新します。1672. 実際の違反を修正する。1683. 管理されたエリアでそれを有効にします。1694. ビルド時間と動作を測定します。1705. 手動メモ化は、不要になった場合にのみ削除してください。171172目標は、すべての `useMemo` を消去することではありません。目標は、レンダリングが怖いという理由で予防的なメモ化を書くのをやめることです。173174## `proxy.ts` とネットワーク境界175176古い `middleware.ts` は `proxy.ts` になります。これは名前の変更ですが、これには意味があります。そのファイルはリクエスト境界に位置し、従来のバックエンド スタイルの汎用ミドルウェアではありません。177178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188189 return NextResponse.next();190}191```192193ここでのルールは単純です。小さく保つことです。リダイレクト、認証ルーティング、ヘッダー、重要な書き換え。 2 つ目のバックエンドのように感じ始めたら、おそらくやりすぎです。194195## 実際にどうやって移住するか196197すべての機能を一度にオンにすることはありません。私だったらこうします:1981991. Next、React、React DOM を更新します。2002. 公式 codemod を起動します。2013. `params`、`searchParams`、`cookies()`、`headers()`、`draftMode()` の重大な変更を修正しました。2024. `middleware.ts` を `proxy.ts` に移行します。2035. 私はビルドと重要なページをチェックします。2046. 現在キャッシュによって摩擦が生じているセクションでキャッシュ コンポーネントを有効にします。2057. 私はタグと無効化の規則を定義します。2068. React Compiler を個別に試してみます。2079. 前後のメトリクスの比較。208209優れた移行とは、すべての新機能を使用するものではありません。これにより、アプリの動作が読みやすくなります。210211## 考え方で何が変わるのか212213Next.js 16 の最も便利な点は、インテンションに適切な名前を付けられることです。機能は単に「データベースから商品を取得する」だけではありません。それは、「商品を入手し、何時間でもキャッシュできます。このタグで無効にします」です。コンポーネントは単に「ページをレンダリングする」だけではありません。それは、「これは高速シェルであり、この作品は個人的なものであり、これはストリーミングで提供されます。」です。214215最初はもっと仕事が必要なように思えます。そうすれば、それは穏やかな形になります。パフォーマンスの決定は、デフォルト、ヒューリスティック、および部族の記憶の組み合わせに隠れることはなくなりました。それらはコードの中にあります。216217## 役立つ情報源218219- [Next.js 16 リリースノート](https://nextjs.org/blog/next-16)220- [キャッシュ コンポーネント - Next.js ドキュメント](https://nextjs.org/docs/app/getting-started/cache-components)221- [キャッシュを使用する - Next.js ドキュメント](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [反応コンパイラ v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16、キャッシュ コンポーネントと React コンパイラー: 実際に何が変わるのかlines 1-223 (END) — press q to close