SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Next.jsがApp Routerの"次"に目指すもの

Next.js 15の新機能――Next.jsが次に見据えるキャッシュ制御

Next.jsがApp Routerの"次"に目指すもの 第3回

"use cache" はパラメータの扱いが賢い

 さて、いくつかのパターンで"use cache"の使い方を解説してきましたが、軽く流してきた中に、非常に重要な点がありました。それは、"use cache"はパラメータの扱いが賢いという点です。

 リスト4では、decodeBase64()関数の実行結果がパラメータごとに別々にキャッシュされていたことを思い出してみてください。開発者である私たちは、「base64strという引数をキーにしてキャッシュを管理してほしい」という指示をしていません。しかし、実際の挙動はそうなっています。

 これはNext.jsがプロジェクトをコンパイルする際に、 "use cache"を指定した関数の引数を認識し、キャッシュのキーとして利用する形のコード生成を行なっているのです。これはコンポーネント関数についても同じで、"use cache"を指定したコンポーネントのpropsはキャッシュのキーとして利用されます。

 リスト7で少し複雑なケースを見てみましょう。

[リスト7]クロージャにuse cacheを指定する
function Profile({ id }) {
  async function getNotifications(index, limit) { // (1)
    "use cache";
    return await db
      .select()
      .from(notifications)
      .limit(limit)
      .offset(index)
      .where(eq(notifications.userId, id)); // (2)
  }
 
  return <User notifications={getNotifications} />;
}

 このコードは、ProfileコンポーネントがUserコンポーネントを呼び出すケースです。UserコンポーネントはgetNotifications()関数をpropsとして受け取り、この関数を呼び出してデータベースから通知を取得します。(1)でgetNotifications()をクロージャとして実装しており、ここにだけ"use cache"を指定しています。

 この場合、getNotifications()関数に渡すindexlimitがキャッシュのキーとして利用されそうなことは想像がつきますね。

 しかし、このデータベース呼び出しでは、Profileコンポーネントのidpropsも(2)のように利用されています。コンパイラはどのように扱うのでしょうか。

 実は、コンパイラはかなり賢いようで、indexlimitに加えてidもキャッシュのキーとして利用します。つまり、getNotifications()関数のキャッシュは、idindexlimitの3つの組み合わせが同じ場合だけ、同じキャッシュが使われるのです。

 コンポーネントや関数がどんなパラメータに依存して処理結果(=キャッシュ対象のデータ)を生成するかは、コンパイラが自動で認識してくれるので、開発者はそのパラメータを意識しなくてもよいというわけです。素晴らしいですね。

 なお、childrenをはじめとした一定以上複雑な(シリアライズできない)パラメータはキャッシュ対象にならないので、Static Rendering対象のコンポーネントの子にDynamic Rendering対象のコンポーネントを配置するような運用も可能です。

キャッシュを破棄する方法

 最後に、キャッシュを破棄する方法を解説します。"use cache"を指定した関数やコンポーネントは、unstable_cacheLife()unstable_cacheTag()といったAPIを利用してキャッシュの有効期間やキャッシュのタグを指定することで、キャッシュを破棄することができます(リスト8)。

[リスト8]app/date.js
import {
  unstable_cacheTag as cacheTag,
  unstable_cacheLife as cacheLife,
} from "next/cache";

export async function getDate1() {
  "use cache";

  const date = new Date();
  cacheTag("date"); // (1)

  return date.toISOString();
}

export async function getDate2() {
  "use cache";

  const date = new Date();
  cacheLife("hours"); // (2)

  return date.toISOString();
}

 (1)のcacheTag()は、キャッシュのタグを指定するAPIです。cacheTag()に渡した文字列は、キャッシュのキーとして利用されます。従来のキャッシュ機構でfetch()にタグを付けていたのと同じような仕組みで、従来と同じようにServer Actions等でrevalidateTag()を呼び出すことでキャッシュを破棄することができます。

 (2)のcacheLife()は、キャッシュの有効期間を指定するAPIです。引数の文字列に対応した時間をキャッシュのフレッシュな期間とし、その時間が経過すると、5分程度の猶予期間(stale時間)の間に古いキャッシュを返しつつ新しいキャッシュを構築します。HTTPヘッダーのCache-Controlにあるstale-while-revalidateと同じような仕組みですね。公式ドキュメントによれば、次のような種類があります。

  • default:15分(stale時間なし、破棄はしない)
  • seconds:1秒(stale時間5分、1分で破棄)
  • minutes:1分(stale時間5分、1時間で破棄)
  • hours::1時間(stale時間5分、1日で破棄)
  • days:1日(stale時間5分、1ヶ月で破棄)
  • weeks:1週間(stale時間5分、1ヶ月で破棄)
  • max:1ヶ月(stale時間5分、破棄はしない)

 これらのAPIは、 "use cache"を指定した関数やコンポーネントの中で呼び出す必要があります。

まとめ

 新しいキャッシュ機構は、後方互換を保ちつつも、従来のキャッシュ機構とはかなり違った発想で設計されていますが、基本的な方針は次の3つです。

  • Static Renderingにしたければ"use cache"を指定する
  • Static Rendering内のキャッシュを更新したければunstable_cacheLife()unstable_cacheTag()で更新する
  • Dynamic Renderingでオンデマンドに情報を出したければ<Suspense>の中でPartial Prerenderingして、<Suspense>の外側がStatic Renderingの対象になるようにする

 従来のキャッシュの方針と比べると、だいぶ意識する情報が減っているように思います。正式リリースはまだ少し先になるかもしれませんが、リリースされたらぜひ使ってみたいですね。

 これからもNext.jsの進化に期待しつつ、本連載はここまでとします。ありがとうございました。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Next.jsがApp Routerの"次"に目指すもの連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川 幸哉(ナカガワ ユキヤ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/21221 2025/04/02 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー