[Next.js] ISR の prefetch 時にはページの再生成がトリガーされない

2023/01/05に公開

どういうこと?

Next.js の next/link でリンクを作成すると、遷移先ページ生成に必要なデータが事前(マウスオーバー時など)に取得される prefetch という機能があります。

遷移先ページが ISR のページの場合、prefetch で取得されるデータも revalidate で指定した秒数ごとに再生成されるのかと思いきや、実際には再生成はトリガーされず、revalidate の時間が経過しても STALE なキャッシュが返され続けます。

リンクをクリックして実際にページに遷移すると再生成がトリガーされ、次にアクセスする際は新しいページが取得できます。

理由

以下の PR でそのような動作になるように変更が加えられたためです。
https://github.com/vercel/next.js/pull/37201

prefetch 時には purpose: prefetch というヘッダが付与されるようになっており、これが付与されている場合はページの再生成をトリガーしないようになっているようです。
実際にページに遷移する際は、このヘッダが付与されない HEAD リクエストが送信されるため、再生成がトリガーされます。

対象バージョン

Next.js 12.2 で上記の変更が取り込まれているため、これ以降のバージョンが対象となります。
https://github.com/vercel/next.js/releases/tag/v12.2.0

おわりに

開発環境で prefetch のレスポンスを確認していたところ、いつまで経っても STALE なキャッシュが返ってくるので疑問に思い、今回調査したところ仕様であることがわかりました。

誰かがそのページに実際に遷移すれば再生成がトリガーされるので、プロダクション環境ではほとんど影響はないと思います。

Discussion