Skip to content

refactor(brand): index.html のブランド値をビルド時に差し込む (ISSUE-3) - #68

Merged
hidari merged 5 commits into
mainfrom
refactor/index-html-build-transform
Oct 29, 2026
Merged

hidari merged 5 commits into
mainfrom
refactor/index-html-build-transform

Conversation

@hidari

@hidari hidari commented Oct 29, 2026

Copy link
Copy Markdown
Owner

概要

index.html に生成した値を持たせるのをやめた。OGP の ?v= と寸法、ヘッダーロゴの寸法の 3 つは、Vite の transformIndexHtml がビルドのたびに配信物から作って差し込む。just images は index.html に触らなくなる。

判断の軸はコード量ではなく構造の堅牢さで、間違った値や欠けた値が、配信するどの経路でも赤くなることを目標にした。比べた案と決定、実測した前提は ISSUE-3 に残した。

Closes ISSUE-3

変更

  • index.html には {{COSPL_*}} のトークンだけを置く。src/brand/outputs.ts の renderIndexHtml がトークンの件数・置き場所・未知の名前・形の崩れを検査し、生成する meta とロゴの img がそれぞれ 1 つだけあることも数える。旧 syncIndexHtml は og:image が 2 つで twitter:image が無い HTML を通していた
  • ?v= はマスター SVG ではなく、配信する public/ogp/ogp-landscape.jpg のバイト列のハッシュから作る。描き直して中身が変われば、マスターが同じでも X のカードキャッシュを外せる
  • dev では、@cloudflare/vite-plugin の下でフックの throw の理由が失われる(HTTP 200 と汎用の文言になる)。そのため理由を console.error してから止める
  • useImportExtensions をリポジトリ全体で必須にした。vite.config.ts から src/ を拡張子なしで読むと、Vite 8 の configLoader が警告を出すため
  • just check-brand-html を足した。deploy.yml はこれを、デプロイ前の dist/client とデプロイ後の本番に当てる。e2e/head.spec.ts は preview と本番の応答だけから期待値を導いて確かめる

リリース時に起きること

  • 最初の site-v* のデプロイで、?v= が 74a3a48c(SVG のハッシュ)から 49708eaa(jpg のハッシュ)へ 1 回だけ変わる。X のカードは 1 回だけ取り直される
  • 今の本番に新しい検査を当てると、?v= の不一致で赤くなる。これは意図した対照で、マージ前に just check-brand-html https://cospl.org と E2E_BASE_URL=https://cospl.org の head.spec で確かめた
  • この PR より前のタグへロールバックすると、E2E (production) の head.spec が赤くなる(main の spec を古い HTML に当てるため)

検証

  • just check: Biome 78 ファイル、vitest 25 ファイル 498 件、tsc 3 構成が通過
  • just build: (!) の警告 0 件。just check-brand-html dist/client が ok
  • dev: 値が差し込まれることと、トークンを消すとターミナルに理由が出ることを curl で確かめた
  • 変異注入: 検査対象を壊す・検査機構を壊す・取り付けを外すの 3 種を 1 つずつ入れ、各検査が狙った理由で赤くなることを確かめた。check-brand-html は値の形だけを見るので、幅と高さの入れ替えとロゴの 1px のずれは head.spec のデコードだけが捕まえる(意図どおり)
  • E2E(merge-gate.yml の固定コンテナ、全ブラウザ): 152 passed / 12 skipped / 0 failed。skip は head.spec の配信内容の 3 件 × chromium 以外の 3 ブラウザと、元から chromium だけの offline.spec の 3 件
  • 見送ったレビューの指摘: deploy 前後の bash 検査を消す案(プラグインを外す変異ではビルドが成功してトークンが残り、デプロイを止められるのはこの検査だけ)、jpg の SOF から寸法を読む案(Merge Gate の E2E のデコードがマージ前に捕まえる)、deploy.yml のリトライの共通化(既存の health check をローカルで検証できないまま書き換えることになる)
  • ISSUE-4: HTML だけの変更では Service Worker のキャッシュ版数が上がらない件を、この PR の作業中に見つけて起票した(この PR では直さない)

ISSUE-3 は index.html のブランド値をビルド時に差し込む作業で、比べた案と決定、実測した前提をスナップショットとして残す。

ISSUE-4 はその調査中に見つけた既存の挙動で、HTML だけの変更では Service Worker のキャッシュ版数が上がらない件。ISSUE-3 では直さない。
just images が index.html を正規表現で書き換える方式をやめ、index.html にはトークンだけを置く。値は vite.config.ts のプラグインが transformIndexHtml で、dev の配信とクライアントのビルドのたびに配信物から作って差し込む。

- og:image / twitter:image の ?v= は、マスター SVG ではなく配信する public/ogp/ogp-landscape.jpg のバイト列のハッシュから作る。描き直して中身が変われば、マスターが同じでも X のカードキャッシュを外せる。最初のデプロイで ?v= が 74a3a48c から 49708eaa へ 1 回だけ変わる
- トークンは置いてよいタグとの組で持ち、件数・置き場所・未知の名前・形の崩れを検査する。生成する meta とロゴの img がそれぞれ 1 つだけあることも数える。旧 syncIndexHtml は og:image が 2 つで twitter:image が無い HTML を通していた
- dev ではフックの throw の理由が本文にもターミナルにも出ないため、理由を console.error してから止める
- vite.config.ts から読む連鎖の import に .ts 拡張子を付け、Biome の useImportExtensions で付け忘れを止める(configLoader の警告を出さないため)
- 同じ検査を just check-brand-html にまとめ、deploy.yml がデプロイ前の dist/client とデプロイ後の本番に当てる。e2e/head.spec.ts は preview と本番の応答だけから期待値を導いて確かめる
vite.config.ts から読む連鎖だけに useImportExtensions を効かせていた override をやめ、リポジトリ全体で有効にした。override の includes は config の import の連鎖を手で写したもので、連鎖に新しいファイルが入ると lint は緑のまま configLoader の警告だけが戻る。全体で有効にすれば写しが要らず、import の書き方も 1 つにそろう。

変更は Biome の自動修正による拡張子の追加だけで、tsc(3 つの tsconfig)・vitest・vite build・just images が .ts の付いた import を解決することを確かめた。
- スロット表のキーをリテラルの型にし、各スロットに「ちょうど 1 つだけあるべきタグ」を持たせた。meta の一覧と数える正規表現の二重管理と、検査済みのあとに通らない ?. や ?? の分岐がなくなる。テンプレートの検査は Option を返す
- buildIndexHtml のテストは renderIndexHtml を期待値に使わず、リテラルで比べる。renderer が壊れたときに両方が同じように壊れて緑になっていた
- index.html のテンプレートのテストは、失敗したときに理由が差分に出るようにした
- 置き残しの検出から }} を外した。Cloudflare が差し込むビーコンの入れ子の JSON が持ち、注入が戻ると誤検出する。形の崩れたトークンも {{ か COSPL_ のどちらかを残すので、検出の範囲は変わらない
- e2e/head.spec.ts は配信された中身だけを見る 3 件を chromium に絞り、画像のデコードだけを全ブラウザで走らせる。ロゴのパスは LOGO.light から作り、viewBox は 4 つの有限の数であることも確かめる
- vite.config.ts の読み込みをバイト列に揃え、古くなったコメントを直した
タスクを全部消化したので closed/ へ移す。import の拡張子は、レビューを受けて config の連鎖に限らずリポジトリ全体で必須にした。ISSUE-4 は open のまま残す。
@hidari hidari self-assigned this Oct 29, 2026
@hidari
hidari merged commit 374ad9c into main Oct 29, 2026
4 checks passed
@hidari
hidari deleted the refactor/index-html-build-transform branch October 29, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant