はじめに
PageSpeed Insightsでトップページだけ100点を取るのは、それほど難しくありません。インラインCSS、最小限のDOM、画像なし。条件を揃えれば達成できます。
本当に難しいのは、サイト内の全ページタイプで100点を維持することです。記事詳細ページには動的コンテンツがあり、チームページにはスタッフカードのグリッドがあり、ツールページにはインタラクティブなJavaScriptがあります。ページタイプごとに異なる課題が潜んでいるのです。
この記事では、京谷商会の18ポータルサイト基盤(Cloudflare Workers上のSSRアプリケーション)において、全7種のページタイプでPerformance・Accessibility・Best Practices・SEOの4項目すべて100点を達成するまでの過程を、実際のLighthouse監査結果と修正コードとともに記録します。
対象サイトの構成
今回の対象は、1つのCloudflare Workerが18のサブドメインを動的にルーティングするポータルシステムです。テンプレートエンジンを使わず、TypeScriptの文字列テンプレートリテラルでHTMLを直接生成するSSR構成を採用しています。
ページタイプは以下の7種類です。
| ページタイプ | URL例 | 特徴 |
|---|---|---|
| トップページ | / |
記事カードグリッド、サムネイル画像 |
| 記事一覧 | /articles/ |
ページネーション、カードリスト |
| 記事詳細 | /articles/{slug}/ |
Markdownレンダリング、目次、著者情報 |
| チーム | /team/ |
スタッフカードグリッド、アバター |
| スタッフ詳細 | /team/{code}/ |
プロフィール、担当記事一覧 |
| 用語集 | /glossary/ |
五十音グループ、カードリスト |
| ツール | /tools/ |
PageSpeed診断(SEOポータルのみ) |
トップページは既に全項目100点を達成済みでした。問題は残りの6タイプです。
発見された問題と修正
問題1:mainランドマークの欠如(Accessibility −9点)
Lighthouseの指摘は landmark-one-main — 「ドキュメントにメインのランドマークが設定されていません」でした。
共通レイアウト関数 layout() では、ヘッダーとフッターの間にコンテンツを直接挿入していました。スクリーンリーダーは <main> 要素を使ってページの主要コンテンツ領域を特定するため、この要素がないとナビゲーション効率が大幅に低下します。
修正内容として、layout() 関数内でコンテンツを <main> タグで囲みました。この1行の修正が全ページタイプに自動的に適用されます。共通レイアウト関数を持つアーキテクチャの強みです。
問題2:canonical URLのパス未設定(SEO −8点)
Lighthouseの指摘は canonical — 「ドキュメントに有効な rel=canonical が指定されていません」でした。
<link rel="canonical"> タグ自体は存在していましたが、パス部分が常に / にフォールバックしていました。チームページ(/team/)のcanonicalがトップページ(/)を指している状態は、Lighthouseが「無効」と判定します。
原因は、パスを渡すためのグローバル変数がどこからも設定されていなかったことです。
修正内容として、Honoミドルウェアを追加し、全リクエストで現在のURLパスをグローバルに設定しました。Cloudflare Workersはリクエストごとに独立したコンテキストで実行されるため、グローバル変数の競合リスクは事実上ありません。12個のレンダリング関数すべてにパス引数を追加するよりも、変更量が圧倒的に少なく済むアプローチです。
問題3:テキスト内リンクの識別不能(Accessibility −7点)
Lighthouseの指摘は link-in-text-block — 「リンクは色に依存して識別可能です」でした。
グローバルCSSで a { text-decoration: none; } を設定していたため、リンクと通常テキストの区別が色のみに依存していました。WCAG 2.1の達成基準1.4.1は、色だけに依存せずにリンクを識別できることを要求しています。
具体的には、パンくずリストのリンク色(#64748b)と周囲テキスト色(#4b5563)のコントラスト比が1.58:1しかなく、基準の3:1を大幅に下回っていました。
修正内容として、デフォルトのリンクスタイルをアンダーライン付きに変更し、ナビゲーション要素やカードリンクのみアンダーラインを除外する方針に転換しました。text-decoration-skip-ink: auto の指定により、アンダーラインが文字のディセンダー(g、y、pなどの下に伸びる部分)と重なる箇所で自動的に途切れ、視認性を維持しつつデザインの美しさを損ないません。
問題4:Coming Soonカードのコントラスト不足(Accessibility −7点)
Lighthouseの指摘は color-contrast — 「背景色と前景色には十分なコントラスト比がありません」でした。
SEOポータルのツール一覧ページには、開発中のツール2つが opacity: 0.5 のカードとして表示されていました。親要素の opacity は子要素すべてに継承されるため、テキストの実効コントラスト比が基準を下回ります。
修正内容として、opacity による「無効化」表現を廃止し、border-style: dashed と color: var(--text-muted) の組み合わせに変更しました。破線ボーダーは「未完成」「準備中」を視覚的に伝える表現として直感的であり、コントラスト比の問題も発生しません。
問題5:ポータルごとのアクセントカラーとボタンコントラスト
18ポータルはそれぞれ異なるテーマカラー(--accent)を持っています。一部のポータルでは、background: var(--accent); color: #fff のボタンがコントラスト基準4.5:1を満たしていませんでした。
修正内容として、ボタンの背景色を var(--accent) から var(--primary-header) に変更しました。--primary-header はヘッダー背景にも使われる暗い色で、白文字との組み合わせで全ポータルにおいて十分なコントラスト比を確保できます。
修正の検証結果

全修正をデプロイした後、Google PageSpeed Insights APIを nocache=1 オプション付きで呼び出し、キャッシュを無視した新鮮なスコアを取得しました。
| ページタイプ | ポータル | Performance | Accessibility | Best Practices | SEO |
|---|---|---|---|---|---|
| チーム | SEO | 100 | 100 | 100 | 100 |
| 用語集 | SEO | 100 | 100 | 100 | 100 |
| ツール(SEO) | SEO | 100 | 100 | 100 | 100 |
| 記事一覧 | SEO | 100 | 100 | 100 | 100 |
| 記事詳細 | SEO | 100 | 100 | 100 | 100 |
| ツール(NoTools) | ADS | 100 | 100 | 100 | 100 |
| チーム | CLD | 100 | 100 | 100 | 100 |
全ページタイプ、複数ポータルにまたがって全項目100点を確認しました。
アーキテクチャが支えた効率的な改善
今回の改善で修正したファイルは実質2つだけです。全ページのHTMLテンプレートを含む render.ts と、ルートハンドラおよびミドルウェアの index.ts です。
1つの layout() 関数が全ページタイプの共通構造を生成しているため、<main> タグの追加やリンクスタイルの変更が自動的に全ページに反映されました。テンプレートの共通化は、保守性だけでなく品質の均一化にも直結します。
また、Cloudflare WorkersのSSR構成はPageSpeed Performanceの面でも有利です。エッジサーバーで即座にHTMLを生成して返すため、TTFB(Time to First Byte)が極めて短く、外部リソースへの依存もありません。JavaScriptフレームワークのハイドレーションコストもゼロです。
100点を維持するために
スコアを一度達成することと、維持し続けることは別の課題です。
定期的な自動計測として、PageSpeed Insights APIをCI/CDパイプラインやcronジョブに組み込み、スコアの低下を早期に検知する仕組みが有効です。当サイトのPageSpeed診断ツールでも手動での確認が可能です。
新規ページタイプ追加時のチェックとして、新しいテンプレートやコンポーネントを追加する際は、必ずキャッシュを無視したPageSpeedテストを実行してください。特に opacity や color の使い方はAccessibilityスコアに直結します。
外部リソース追加の慎重な判断も重要です。Google Fontsやアナリティクススクリプトの追加は、Performance 100点を崩す最大の要因になります。本当に必要か、代替手段はないかを検討してください。
まとめ
今回の改善で対処した問題は、いずれも「動くし見える、でもLighthouseが減点する」類のものでした。<main> タグがなくてもページは表示されますし、アンダーラインがなくてもリンクは機能します。しかし、これらの基準を満たすことは、スクリーンリーダーのユーザーや色覚特性を持つユーザーにとって、サイトが使えるかどうかの分かれ目です。
PageSpeed Insightsの100点は目標ではなく基準線です。全項目100点を全ページタイプで達成した今、次に取り組むべきは実ユーザーデータ(CrUX)での検証と、コンテンツ追加に伴うスコア維持の仕組みづくりです。
参考リンク
Lighthouseのアクセシビリティ監査の詳細はLighthouse accessibility scoringで確認できます。今回問題となったリンク識別の基準はWCAG 2.1 達成基準1.4.1 色の使用に定められています。canonical URLの正しい設定方法はGoogle検索セントラル canonical タグが公式ガイドです。Cloudflare WorkersでのSSR構成についてはCloudflare Workers documentationを参照してください。mainランドマークの仕様はWAI-ARIA main landmarkに解説されています。