Astro の <ClientRouter /> 導入メモ
ページ遷移時のちらつき(FOUC)が気になったため、Astro の <ClientRouter /> を導入して解決したときのメモ。
追記(2026/04/11):
FOUC の原因を解消したため、現在は <ClientRouter /> を使用していない。
参照:ページ遷移のちらつき(FOUC)は @view-transition が原因だった
Astro の <ClientRouter /> とは
Astro の <ClientRouter /> は、ページ遷移のアニメーションを追加したり、クライアントサイドルーティングを有効にして、SPA(シングルページアプリケーション)のような振る舞いにするコンポーネントだ。
<ClientRouter /> コンポーネントを <head> 内に追加することで導入できる。
これだけで FOUC の問題が解決した。
スクリプトの再実行
Astro のスクリプトは通常 1 回しか実行されない。 そのため、クライアントサイドルーティングによってページの一部が置き換わるようになると、ページ遷移後にスクリプトが実行されなくなる。
ページ遷移後に実行が必要なスクリプトに対しては、以下の対応を行った。
astro:after-swap
astro:after-swap は、ページ遷移して新しい DOM に置き換わったとき(描画前)に発生するライフサイクルイベントだ。
初回表示や再読み込み時には発生しない。
テーマの設定に使用した。
<script is:inline> function applyTheme() { const theme = (() => { const localStorageTheme = localStorage?.getItem("theme") ?? ""; if (["dark", "light"].includes(localStorageTheme)) { return localStorageTheme; } if (window.matchMedia("(prefers-color-scheme: dark)").matches) { return "dark"; } return "light"; })(); document.documentElement.setAttribute("data-theme", theme); window.localStorage.setItem("theme", theme); }
document.addEventListener("astro:after-swap", applyTheme); applyTheme();</script>astro:page-load
astro:page-load は、ページ読み込みの最後に発生するライフサイクルイベントだ。
ページ遷移のたびに発生するため、基本的にはこれを使用すればよい。
<script> function setupTOC() { ... }
setupTOC(); document.addEventListener("astro:page-load", setupTOC);</script>スムーススクロールの限定
ページ全体にスムーススクロールを設定していたので、クライアントサイドルーティングによってブラウザの戻る操作をした際にも、スクロールのアニメーションが発生するようになった。
スムーススクロールは見出しのアンカーリンクでのみ適用したかったため、:has() と :target を使って対応した。
<html lang={site.lang} class="scroll-smooth bg-base-100 text-base-content antialiased" class="has-[:target]:scroll-smooth bg-base-100 text-base-content antialiased">まとめ
<ClientRouter />は、ページ遷移のアニメーションを追加したり、部分的な DOM 置換を可能にするコンポーネント。astro:after-swapやastro:page-loadなどのイベントを使用することで、ページ遷移後のスクリプト実行を制御できる。:has()と:targetを組み合わせれば、スムーススクロールの適用範囲をアンカーリンクのみに限定できる。