テック技報最新号へ →
コード

Next.js 16.4: instant() で「クリック前に表示できるUI」をテストし、プリフェッチを調整する

@next/playwright の instant() で囲んだ範囲では、遷移が始まってから届くデータが止められる。だから「プリフェッチ済みの内容だけで何が見えるか」をアサートできる。このテストを先に書いてから、キャッシュとプリフェッチの設定を直していく。

@nextjs · 投稿 2026-10-17
#nextjs#prefetch#cache-components#playwright#testing

どんな問題を解決する?

  • 一度開いたページに戻ってもスケルトンが出る
  • prefetch={true} で一覧のカードを全部先読みしてしまい、リクエスト数やコストが増える
  • 「速くなったはず」を目視でしか確認できず、あとで知らないうちに元に戻る

やり方

前提: Cache Components と Partial Prefetching が有効(16.4 の create-next-app では既定)。

ts
// next.config.ts
const nextConfig: NextConfig = { cacheComponents: true, partialPrefetching: true };

ルート単位で試すなら、そのルートで export const prefetch = 'partial' を宣言する。

  1. 目標をテストにする
    ts
    import { instant } from '@next/playwright';
    import { expect, test } from '@playwright/test';
    
    test('詳細のヘッダーはクリック前に用意されている', async ({ page }) => {
      await page.goto('/templates');
      await instant(page, async () => {
        await page.getByTestId('template-card-link').first().click();
        await page.waitForURL('**/templates/*');
        await expect(page.getByTestId('detail-skeleton')).toHaveCount(0);
        await expect(page.getByTestId('detail-title')).toBeVisible();
      });
    });

    今の UI で通るテストを書く。次に目標のアサーションを足して、失敗することを確認する。

  2. データの種類ごとにキャッシュを分ける
    • 全員で共有できる公開データは 'use cache: remote'。Vercel では Runtime Cache に入る。自前の next start では、cacheHandlers.remote を設定しないとメモリに置かれる。
    • ユーザーごとのデータは 'use cache: private'(ブラウザ側に保持)。[scope] などを引数で渡すと、その値がキャッシュキーに入る。
    • 寿命は cacheLife('hours') や cacheLife({ stale: 300 })、無効化のキーは cacheTag(...) で指定する。更新時は revalidateTag()(後のリクエストで更新)か、Server Action 内で updateTag()(その往復ですぐ反映)を呼ぶ。
  3. キャッシュした先を <Link prefetch={true}> でプリフェッチする。動的ルートでも、行き先の URL を解決してキャッシュ済みの部分まで先読みする。
  4. 大きな一覧ではユーザーの意図が見えてから先読みする
    tsx
    const [intent, setIntent] = useState(false);
    <Link href={href} prefetch={intent ? true : 'auto'}
      onMouseEnter={() => setIntent(true)} onFocus={() => setIntent(true)}
      onTouchStart={() => setIntent(true)} />
  5. 優先度の低い部分は navigation() の後ろに回す。import { navigation } from 'next/cache' を await した後のキャッシュ処理は、プリフェッチでは走らない。実際に遷移したときに実行され、戻ってきたときは再利用される。<Suspense> で囲んで使う。
  6. ビルドしてテストを再実行し、通るまで 2〜5 を繰り返す。通ったテストは CI に残して、退行を防ぐ。

注意点

出典

X の元の投稿を開く