Parent: #73 (PR #140 で prerendered ページと sitemap を導入・本番検証済み)
Priority: P3 — 現状で受入条件は満たしている。以下は読者体験の改善。
/decl/<slug>/ の静的ページは、クローラ向けの索引可能性という目的は達成している(sitemap 1426 URL、本番で符号化 24 件 + 抽出 45 件すべて 200)。一方、検索エンジンから直接着地した読者 の体験には 2 つ改善余地があり、#140 では意図的にスコープ外とした。両方とも「やるなら設計判断が要る」ため、まとめてここで追う。
1. KaTeX の事前レンダリング
現状 : ページは TeX 区切り($…$ / $$…$$)をそのまま出力し、site/decl-page.js がブラウザで描画する。JS 無効時・クローラからは素の TeX が見える(索引対象としては妥当だが、読者には読みにくい)。
検討事項 :
ビルド時に KaTeX でレンダリングして HTML を埋め込むと、JS 無しでも数式が読める。ただしページあたりのサイズが増える(現状 1425 ページで 1.38 MiB gzip。KaTeX の HTML 出力は元の TeX より大幅に大きい)。Move generated site data out of source review and add wave growth budgeting #29 の予算(warn 16 MiB raw / 6 MiB gzip、公開ツリー実測 8.5 MiB / 3.0 MiB)への影響を実測してから判断すること。
Node を使わずに Python 側でレンダリングする方法が無い。現在のビルドは純 Python なので、KaTeX の事前レンダリングは Node 依存を CI のビルド段に持ち込む(npm test は既に Node を使うが、build-artifact ジョブは意図的に Node を使っていない — .github/workflows/ci.yml のコメント参照)。
代替: 数式を含む段落だけを対象にする、statement_ja の第 1 段落のみ事前描画する、など部分適用。
2. 静的ページから SPA への水和
現状 : 静的ページは自己完結で app.js を読み込まない。読者は「インタラクティブ表示で開く」リンクで #/decl/<slug> へ移動する(ページ遷移が 1 回挟まる)。
検討事項 :
Acceptance criteria
Parent: #73(PR #140 で prerendered ページと sitemap を導入・本番検証済み)
Priority: P3 — 現状で受入条件は満たしている。以下は読者体験の改善。
/decl/<slug>/の静的ページは、クローラ向けの索引可能性という目的は達成している(sitemap 1426 URL、本番で符号化 24 件 + 抽出 45 件すべて 200)。一方、検索エンジンから直接着地した読者の体験には 2 つ改善余地があり、#140 では意図的にスコープ外とした。両方とも「やるなら設計判断が要る」ため、まとめてここで追う。1. KaTeX の事前レンダリング
現状: ページは TeX 区切り(
$…$/$$…$$)をそのまま出力し、site/decl-page.jsがブラウザで描画する。JS 無効時・クローラからは素の TeX が見える(索引対象としては妥当だが、読者には読みにくい)。検討事項:
npm testは既に Node を使うが、build-artifactジョブは意図的に Node を使っていない —.github/workflows/ci.ymlのコメント参照)。statement_jaの第 1 段落のみ事前描画する、など部分適用。2. 静的ページから SPA への水和
現状: 静的ページは自己完結で
app.jsを読み込まない。読者は「インタラクティブ表示で開く」リンクで#/decl/<slug>へ移動する(ページ遷移が 1 回挟まる)。検討事項:
app.jsはfetch('data/nodes.json')のように相対パスで payload を取る。/decl/<slug>/から読み込むと/decl/<slug>/data/nodes.jsonを見に行くため、そのままでは動かない。<base href="../../">で解決できるが、サイトの CSP がbase-uri 'none'なので使えない([P1][release-engineering] accessibility・workflow security・dependency reproducibility を強化する #72 で意図的に設定されたもの)。したがってapp.js側の取得パスを絶対化するか、ルートを明示的に渡す仕組みが要る = SPA 本体への変更。#/decl/<slug>が付き、静的パスとハッシュルートが 1 画面に同居する。canonical は静的パス側を指しているので、その整合も設計に含める必要がある。Acceptance criteria
app.jsの取得パスをどう解決するか(CSP のbase-uri 'none'を維持したまま)の方式が決まっているか、見送りが記録されているsite/**)とsha256sum -cの検証性を壊さない