はきくま!制作日記:Astro・ClientRouter 編

投稿日

Astro のテンプレートとスタイルの罠、ページ遷移(ClientRouter)でつまずいたところ。


その1:Astro のテンプレートとスタイルの罠

  • .astro の中で <!-- --> でコードをコメントアウトすると、ページが読み込み中のまま止まった。 VSCode のコメントアウトのショートカット(Cmd + /)を素直に使うと、テンプレート部分では <!-- --> が入るので引っかかる。<!-- --> は HTML として出力されるコメントで、中の式が処理対象になる。Astro のテンプレートでは {/* */} を手で書く
  • スコープ付きスタイルは、子コンポーネントの中や set:html で入れた HTML には届かない。 子に渡したい時は ...rest で data-astro-cid-* 属性ごと受け取るか、グローバルの SCSS に書く。縦中横や傍点、リッチエディタの中身の見た目はグローバルへ
  • コンポーネントの <style> は .class[data-astro-cid-xxx] に書き換わり、属性の分だけ強くなる。 共通の部品の中に本文専用の行間を書いていたら、グローバルに書いた人物紹介の行間より常に勝っていた。部品の中には、どこで使っても同じでいい指定だけを置く
  • グローバルの SCSS ファイルでは、.astro の中のように f. や m. が自動で使えない。ファイルの先頭で @use "../../foundation/function" as f;
  • astro add cloudflare が tsconfig.json の include を書き換え、astro:assets や .astro の import がエディタで全部「見つからない」に。.astro/types.d.ts と **/* を戻して npx astro sync、VSCode は「Developer: Reload Window」
  • getElementById の戻り値は null の可能性があるので TypeScript が注意する。同じファイル内に必ずある要素なら !、SVG の要素を探すなら querySelectorAll<SVGElement>
  • iPhone では Chrome も表示エンジンは Safari と同じ WebKit。height: auto の SVG が高さ0になって消えた → aspect-ratio を明示して解決。以来、画像と SVG には必ず aspect-ratio を付けて、レイアウトシフトも防ぐ

その2:縦中横の数字が、ページ遷移の後にずれる

ページ遷移の後だけ、縦中横の数字が右にずれる。リロードすると直る。ウィンドウ幅を変えても変わらず、devtools を開いて1秒ほどで直ったこともあった。

  • 疑ったこと:フォントのスワップ(display=swap)による再レイアウト。display=block にしても変わらず、元に戻した
  • npm run dev を止めたら出なくなり、以降は再現していない。開発サーバーの状態が原因と判断した

学び

  • 「勝手に直る」「効かない」時は、コードを疑う前に開発サーバーの再起動と強制リロード

その3:ClientRouter の導入

古のフレームのような、「左に目次、右に本文、そこだけが入れ替わる」画面を作りたかった。裏サイトは fetch + innerHTML で、表サイトは Astro の ClientRouter を導入することにした。

ClientRouter の目的は、ページ遷移のたびに、メニューや目次が作り直されてちらつくのを止めること。

  • Head.astro の <head> に <ClientRouter />
  • <script> は遷移で再実行されない。クリックは document に委譲し、初期化は astro:page-load で行う
  • 目次の aside は transition:persist={mokuji-${novel.id}} で、遷移しても残す。開閉の状態は localStorage の mokujiHidden に保存し、md 以下は is-closed を付けて始める
  • ヘッダーのメニューは、astro:page-load で閉じる
  • ライトボックスを開いたまま遷移しないよう、astro:before-swap で <dialog> を閉じる
  • JS で作った要素には、Astro のスコープ属性(data-astro-cid-*)が付かない。ページ送りの数字のように JS で作る要素のスタイルは、<style is:global> か :global() に書く
  • プレビューの URL で、遷移しても目次が作り直されないことを確認した

この記事の学び

  • Astro のスタイルは「そのファイルの要素にだけ」効く。届かない時は、グローバルに出すか属性ごと渡す
  • 「効かない」「勝手に直る」は、まず開発サーバーを疑う
  • ClientRouter の下では、スクリプトは1回しか走らない。document への委譲と astro:page-load が基本