6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js(App Router)で「ページリロードだけ」を検知しようとして盛大にハマった話

Last updated at Posted at 2025-12-21

LIFULL Advent Calendar 2025 20日目の記事です。

はじめに(結論)

結論から書くと、Next.js(App Router)で「ページリロード時だけ」を正確に検知する方法は見つけられませんでした
最終的に、この要件は実装スコープから外す判断をしています。

本記事では、beforeunloadPerformanceNavigationTiming といった一見使えそうな Web API を実際に検証し、なぜそれらが App Router では成立しなかったのかを整理します。

やりたかったこと

Next.js(App Router)を使用したアプリケーションで、「ページリロード時」だけを対象に、ある処理を除外する必要がありました。

ここで重要だったのは次の点です。

  • 対象は ページリロードのみ
  • 以下は 対象外
    • 画面遷移(<Link> / router.push
    • ブラウザの戻る / 進む

着手する前は
「リロード検知なら、何か Web API があるだろう」
と考えていました。

しかし、App Router を前提にした瞬間、
「そもそも前提としている挙動が噛み合っていない」
という問題にぶつかりました。

App Router における「遷移」と「リロード」

まず整理しておくべきなのが、App Router における画面遷移が ブラウザのページ遷移ではない という点です。

Next.js(App Router)で <Link> を使って画面遷移すると、内部では次のような処理が行われます。

  1. <Link> をクリック
  2. RSC Payload(シリアライズされた React Tree)を取得
  3. React Tree を差し替えて画面を更新

このとき、

  • HTML ドキュメントは再読み込みされない
  • window / document は破棄されない
  • JavaScript の実行環境はそのまま維持される

という状態になります。

見た目は「ページが変わった」ように見えますが、ブラウザ的にはページを移動していません。

beforeunload を試す

最初に試したのが beforeunload です。

「ページから離れる直前」を検知できる API なので、直感的にはリロード検知に使えそうでした。

期待していたこと

  • リロード時に発火する
  • App Router の画面遷移では発火しない
  • よって「リロードだけ検知できるはず」

実際に起きたこと

  • App Router の画面遷移では発火しない
    → これは想定通り
  • しかし リロード「だけ」を判定することはできなかった

なぜ beforeunload ではダメだったのか

beforeunload が通知するのは、

ページが破棄される直前であること

だけです。

そのため、

  • リロード
  • タブクローズ
  • 別ページへの遷移
  • 戻る / 進む

といった操作を 区別することができません。

「ページから離れる」という事実は分かっても、なぜ離れたのかは分からない という仕様です。

この時点で、

  • 「リロードだけを知りたい」
  • 「理由は問わない API」

というズレがあることが分かりました。

PerformanceNavigationTiming を試す

次に試したのが PerformanceNavigationTiming です。

MDN を確認すると、ナビゲーションの種類を取得できそうでした。

  • reload
  • navigate
  • back_forward

これを使えば、リロードだけを判別できるのではないかと考えました。

App Router での結果

しかし、App Router 環境で確認してみると、

  • <Link> による画面遷移を行っても
  • ナビゲーション種別は常に reload のまま

という結果になりました。

なぜこうなるのか

PerformanceNavigationTiming が対象としているのは、

ブラウザが行うページ遷移

です。

App Router の画面遷移では、

  • 新しい HTML ドキュメントは読み込まれない
  • ブラウザとしての「ページ遷移」は発生しない

そのため、画面が切り替わっても、ナビゲーションとしては扱われません。

結果として、

  • 最後にページが読み込まれたときの状態(reload
  • それ以降は変化なし

という情報しか取得できませんでした。

なぜこの 2 つでは要件を満たせなかったのか

ここまでを整理すると、次のようになります。

試したもの 分かること 分からないこと
beforeunload ページが破棄される 離脱の理由
PerformanceNavigationTiming ブラウザのページ遷移種別 SPA 内の画面切り替え
App Router 画面表示の切り替え ブラウザ遷移の発生

それぞれ 前提としている挙動の範囲が異なる ため、
組み合わせても「リロードだけを検知する」という要件は満たせませんでした。

まとめ

  • beforeunload では、リロードかどうかを判別できない
  • PerformanceNavigationTiming は、SPA の画面遷移を対象としていない
  • App Router の画面遷移は、ブラウザのページ遷移ではない

学び・教訓

  • 同じ「遷移」に見えても、ブラウザが扱う遷移と Next.js が扱う遷移は別物
  • ブラウザ API は SPA の内部状態を前提にしていない
  • 「何を検知したいのか」と「API が何を扱っているのか」を
    最初に揃えて考えないと、簡単にハマる

同じように「リロードだけ検知したい」と考えている方の
遠回りを一つでも減らせれば幸いです。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?