はきくま!制作日記: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が基本