🏷️

Next.js 16のupdateTagとrevalidateTagの挙動を実環境で比較してみた

に公開

Next.js 16 では新たに updateTag()が追加され、revalidateTag()の挙動が変更されたので、実環境にデモをデプロイしてそれらの違いを検証してみました

Next.js 16 で追加された updateTag()

https://nextjs.org/blog/next-16#updatetag-new

  • Next.js 16 では Server Actions 専用のupdateTag()が追加されました
  • 同じリクエスト内でタグ付きキャッシュを即時で期限切れにし、後続のfetchや Cache Component が「書き込み直後の値」を読み込みます

Next.js 16 で変更された revalidateTag()

https://nextjs.org/blog/next-16#improved-caching-apis

  • 第 2 引数を指定するrevalidateTag(tag, profile)の形式に変更されて、profile を指定しない従来の呼び出しは非推奨となりました
    (第 2 引数を指定しない場合は、updateTag()と同じ挙動になるそうです)

    Without profile: legacy behavior which is equivalent to updateTag

  • revalidateTag("tag-name", "max")のように"max"を指定するのが推奨とされています
app/actions.ts
"use server";

import { revalidateTag } from "next/cache";

export default async function submit() {
  await addPost();
  revalidateTag("posts", "max");
}

デモアプリを実装して検証

実際に Server Actions でupdateTag()revalidateTag()を実行するデモアプリを実装しました

パブリックリポジトリにしてあるので、興味があればソースコードものぞいてみてください

https://github.com/usuijuice/revalidate-vs-update

vercelを使って本番環境にデプロイして挙動を確認しました

  • revalidateTag()の第 2 引数は全て"max"を指定しています
  • おまけでrevalidatePath()も検証しています

以下にその結果をまとめます

アクション名 再検証アクションを実行 再検証アクションを実行後にリロード(1 回目) 再検証アクションを実行後にリロード(2 回目)
updateTag() 「サーバーレンダリング時刻」と「タグ付きデータ」がアクションを実行した時刻で更新される 「サーバーレンダリング時刻」と「タグ付きデータ」がリロードした時刻で更新される 変化なし
revalidateTag() 変化なし 変化なし 「サーバーレンダリング時刻」と「タグ付きデータ」が"1回目に"リロードした時刻で更新される
revalidatePath() 「サーバーレンダリング時刻」と「タグ付きデータ」と「タグなし」データがアクションを実行した時刻で更新される 「サーバーレンダリング時刻」と「タグ付きデータ」と「タグなし」がリロードした時刻で更新される 変化なし

特筆するべきは、revalidateTag()を行った後は 2 回目のリロードでデータが更新される点です

  • 1 回目のリロードではサーバー内のキャッシュは更新されますが、クライアントにはキャッシュされていた古いデータが返ってきます
  • 2 回目のリロードではサーバー内のキャッシュはすでに更新されているため、 1 回目にリロードした時刻のデータが返ってきます

開発サーバーでの検証

実環境にデプロイせず、開発環境で検証した際は若干異なる結果となったためまとめます

  • npm run devで開発サーバーを立ち上げた場合

    アクション名 再検証アクションを実行 再検証アクションを実行後にリロード(1 回目) 再検証アクションを実行後にリロード(2 回目)
    updateTag() 「サーバーレンダリング時刻」と「タグ付きデータ」がアクションを実行した時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される
    revalidateTag() 変化なし 「サーバーレンダリング時刻」がリロードした時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新され、「タグ付きデータ」が"1回目に"リロードした時刻で更新される
    revalidatePath() 「サーバーレンダリング時刻」と「タグ付きデータ」と「タグなし」データがアクションを実行した時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される
  • npm run buildnpm run startでローカルサーバーを立ち上げた場合

    アクション名 再検証アクションを実行 再検証アクションを実行後にリロード(1 回目) 再検証アクションを実行後にリロード(2 回目)
    updateTag() 「サーバーレンダリング時刻」と「タグ付きデータ」がアクションを実行した時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される 変化なし
    revalidateTag() 変化なし 変化なし 「サーバーレンダリング時刻」と「タグ付きデータ」が"1回目に"リロードした時刻で更新される
    revalidatePath() 「サーバーレンダリング時刻」と「タグ付きデータ」と「タグなし」データがアクションを実行した時刻で更新される 「サーバーレンダリング時刻」がリロードした時刻で更新される 変化なし

蛇足

今回、検証用のデモアプリを作りましたが、この実装は全て GitHub Copilot Coding Agent に/taskで依頼しました

https://github.blog/changelog/2025-10-28-a-mission-control-to-assign-steer-and-track-copilot-coding-agent-tasks

しかもプロンプトはたったの 1 行です

nextjsのrevalidateTagとupdateTagの挙動をテストできるページを実装してください

GitHub Copilot Coding Agent に実装を依頼して、vercel が自動で PR のコードをテスト環境にデプロイするため、人間による作業はほぼゼロです

この辺りの内容もそのうち記事にしたいと思います!

参考リンク

GitHubで編集を提案

Discussion