結論(過大な初期HTMLを配信していない)
過大な初期HTMLを配信していないとは、ページを開いたときに最初に受け取るHTML文書(初期HTML)が極端に大きくなく、セキュリティAIチェッカーの基準である1,000,000バイト(約1MB)以下に収まっている状態です。巨大なHTMLはスマートフォンでの表示を遅くし、Googlebotが読む先頭2MBを超えると後半がインデックスされない可能性があります。1MBを超えると △ 要確認(重み1)と判定します。
この記事のポイント
- 評価はバイト数で行います。日本語はUTF-8で通常1文字3バイトのため、文字数とは大きく異なります。
- Googlebotは先頭2MBまでをクロールし、この上限は非圧縮のデータに適用されます。
- 診断はContent-Length(なければ本文のUTF-8バイト数)が1,000,000バイト以下で ○、超えると △(0.45点)です。
- 巨大化の典型原因はBase64画像、全件データの埋め込み、__NEXT_DATA__ 等の初期状態データ、インラインCSS/JS、残存した非表示要素です。
- 圧縮は転送量を減らしますが判定は変わらず、HTML自体の削減が本質的な対策です。
| 診断項目名 | 過大な初期HTMLを配信していない |
|---|---|
| 項目ID | headers.content-length |
| 分類 | HTMLの基本衛生 |
| 重大度・配点の重み | 低(low) 重み 1 |
| 関連する標準・ガイドライン | 直接対応するASVS要件はありません(品質・可用性の指標)。参考:RFC 9110(HTTP Semantics)8.6 Content-Length、Google検索セントラル「Googlebot」(HTMLは先頭2MBまでをクロール)、Chrome Lighthouse「Avoid enormous network payloads」 |
過大な初期HTMLを配信していないとは(HTMLサイズの確認)
過大な初期HTMLを配信していないとは、ページを開いたときに最初に受け取るHTML文書(初期HTML)が極端に大きくなく、適切なサイズに収まっている状態のことです。セキュリティAIチェッカーはこの項目(headers.content-length)で、トップページの初期HTMLが1,000,000バイト(約1MB)以下に収まっているかを確認します。
初期HTMLが極端に大きいと、通信量の多いスマートフォンや回線の細い環境で表示が遅くなり、検索エンジンにもページの後半が読み込まれない可能性があります。また、巨大なHTMLは、本来ページに不要な大量データ(全件のお知らせ一覧、Base64で埋め込んだ画像、フレームワークの初期状態データ等)が埋め込まれているサインでもあります。
この項目はセキュリティの脆弱性そのものではなく、可用性・品質面の補助指標として重み1で評価します。
| 項目 | 内容 |
|---|---|
| 項目ID | headers.content-length |
| 診断カテゴリ | 信頼性 |
| 重大度 | low |
| 重み | 1 |
| 関連標準 | 直接対応するASVS要件はありません(品質・可用性の指標)。参考:RFC 9110 8.6 Content-Length、Google検索セントラル「Googlebot」、Chrome Lighthouse「Avoid enormous network payloads」 |
HTMLのサイズはどう測るのか(Content-Lengthとバイト数)
Content-Lengthヘッダー
Content-Length は、応答本文のバイト数を示すHTTPヘッダーです(RFC 9110)。圧縮(gzip、br等)が適用された応答では、圧縮後の転送バイト数を示します。HTTP/1.1のチャンク転送(Transfer-Encoding: chunked)や、HTTP/2・HTTP/3で長さを事前に示さない応答では、このヘッダーが付かないこともあります。
文字数とバイト数の違い
日本語の文字はUTF-8で1文字あたり通常3バイトです。JavaScriptの文字列長(length)は文字数(UTF-16の単位数)を数えるため、日本語中心のページではバイト数の約3分の1の値になります。通信量や検索エンジンの上限はバイト単位で決まるため、サイズの評価はバイト数で行う必要があります。
HTMLサイズの目安はどのくらいか(Googlebot・Lighthouse)
| 出典 | 内容 |
|---|---|
| Google検索セントラル | Google検索用のクロールでは、Googlebotはサポート対象ファイル形式の先頭2MB(PDFは先頭64MB)をクロールする |
| Chrome Lighthouse | ページ全体のネットワーク転送量が5,000KiBを超えると「Avoid enormous network payloads」として指摘。中央値は1,700〜1,900KiB程度で、1,600KiB未満を目標に挙げている |
Lighthouseの基準は画像やスクリプトを含むページ全体の合計であり、HTML単体の上限ではありません。本診断の1MBという閾値は、HTML単体としては明らかに大きく、Googlebotの2MB上限に対しても余裕を残すための経験的な目安です。一般的な自治体トップページのHTMLは数十〜数百KB程度に収まります。
HTMLが巨大化する典型的な原因
- Base64画像の埋め込み:
<img src="data:image/png;base64,...">で画像を直接HTMLに入れている。 - 全件データの埋め込み:お知らせ・イベントの全件をHTMLに出力し、JavaScriptで絞り込み表示している。
- SPA・SSRの初期状態データ:Next.jsの
__NEXT_DATA__やNuxtの__NUXT__に、表示に不要な大きいデータを渡している。 - インラインCSS/JSの肥大化:ページビルダーやCMSテーマが、全ページで巨大なインラインスタイルやスクリプトを出力している。
- 不要なコメントや隠し要素:非表示の過去記事、コメントアウトされた旧デザインのHTMLが残存している。
HTMLサイズについてよくある誤解
- 「圧縮しているから問題ない」:転送量は減りますが、ブラウザは展開後のHTMLを解析・描画する必要があり、端末の処理負荷は減りません。Googleも、Googlebotのファイルサイズ上限は非圧縮のデータに対して適用されると明記しています。
- 「光回線なら速い」:利用者の多くはスマートフォンで閲覧します。災害時など回線が混雑する場面でこそ、軽いページであることが重要です。
過大な初期HTMLを配信していないの診断基準(セキュリティAIチェッカー)
取得対象
- 入力URLへのGET(リダイレクト最大4回追跡)で得た最終ページの応答。
- 診断用の要求は
Accept-Encoding: identity(圧縮を要求しない指定)を付けて送るため、通常は非圧縮の応答が返り、Content-Lengthは展開後のバイト数に相当します。 - 応答本文は最大2,000,000バイトまで受信します。これを超えると取得自体が中断され、診断全体がエラーとなるため、本項目は1,000,000バイト超〜2,000,000バイトの範囲で △ を出します。
サイズの算出
Content-Lengthヘッダーがあれば、その数値を使います。- なければ、受信して文字列化したHTML本文をUTF-8でエンコードしたバイト数を使います。本文はUTF-8として復号するため、Shift_JISやEUC-JPのページでは解釈できないバイトが置換文字(3バイト)に変わり、実際の転送量より大きめに算出されます。
- 根拠欄には「取得したHTMLは約◯KBです。」とバイト数から換算したKB(切り上げ)を表示します。
Content-Lengthが数値として解釈できない場合は、その旨とヘッダー値の先頭40文字を表示します。
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| ○ 問題なし(pass) | サイズが1,000,000バイト以下 | 重み1を満点で加算 |
| △ 要確認(warn) | 1,000,000バイト超、または Content-Length が数値として解釈できない | 重み1×0.45=0.45点 |
- この項目は対象外(na)を返しません。Content-Typeがテキスト系でなく本文を解析しない場合、
Content-Lengthがなければサイズ0として ○ になります。 - × 要改善(fail)の判定もありません。
判定上の注意
Content-Lengthは応答ヘッダーの申告値です。サーバーが圧縮を強制して返した場合は圧縮後のサイズとなり、実際のHTMLより小さく評価されます。- 評価対象は最初に返るHTML文書だけで、画像・CSS・JavaScript・後から読み込まれるデータは含みません。ページ全体の重さはLighthouse等で別途確認してください。
- トップページ以外(大きな一覧ページ等)は評価しないため、必要に応じて該当ページのURLを指定して診断してください。
自治体サイトでの判定例
| 状況 | 判定 |
|---|---|
| CMSで生成した標準的なトップページ(HTML 80KB) | ○ |
| トップページのスライダー画像6枚をBase64でHTMLに埋め込み、合計1.4MB | △ |
| 全お知らせ5,000件をHTMLに埋め込み、表示時にJavaScriptで最新10件だけを見せている | △ になりやすい |
初期HTMLが過大だとどんなリスクがあるか
- 可用性の低下:アクセス集中時(災害時の避難情報、給付金の受付開始など)に、1リクエストあたりの転送量が大きいとサーバーや回線の負荷が増え、つながりにくくなります。自治体サイトは平常時と非常時のアクセス差が大きく、軽量化は非常時の情報提供能力に直結します。
- 閲覧者の負担:モバイル回線の通信量を消費し、低スペック端末で表示や操作が遅くなります。
- 検索・情報到達性の低下:HTMLがGooglebotの上限(2MB)を超えると、それ以降の内容がインデックスされない可能性があります。
- 情報露出の副作用:表示に不要な全件データや非表示要素の中に、公開予定前の情報や内部向けのメモが含まれていることがあります。
初期HTMLを軽量化する方法(原因の特定・Next.js・CMS・圧縮設定)
1. 何が大きいのかを特定する
# 非圧縮のサイズ(診断と同じ条件)
curl -s https://www.city.example.lg.jp/ | wc -c
# 圧縮転送時のサイズ
curl -s -H 'Accept-Encoding: gzip, br' -o /dev/null -w '%{size_download}\n' https://www.city.example.lg.jp/
# Base64埋め込み画像の量
curl -s https://www.city.example.lg.jp/ | grep -o 'data:image/[a-z+]*;base64,[A-Za-z0-9+/=]*' | wc -c
ブラウザの開発者ツール(Network)で文書の「Size」を確認し、Elementsで大きな script 要素や <img src="data:..."> を探します。
2. 原因別の対処
| 原因 | 対処 |
|---|---|
| Base64画像 | 画像ファイルとして配置し <img src="/img/top1.webp" loading="lazy"> で参照 |
| 全件データの埋め込み | 一覧は最新数件のみ出力し、続きは一覧ページやページングへ |
__NEXT_DATA__ 等の肥大 | ページへ渡すpropsを表示に必要な項目に絞る。Server Componentsで必要部分だけ描画 |
| インラインCSS/JS | 共通部分を外部ファイル化してブラウザキャッシュを活用 |
| 不要なコメント・非表示要素 | テンプレートから削除 |
2-1. Next.js:ページへ渡すデータを絞る例
// app/page.tsx(App Router・Server Component)
export default async function Home() {
const all = await getNews(); // 全件取得
const latest = all.slice(0, 10).map(({ id, title, date }) => ({ id, title, date }));
return <NewsList items={latest} />; // 表示に必要な項目・件数だけをクライアントへ
}
Client Componentへ渡したpropsはHTML内のシリアライズ済みデータとして埋め込まれます。本文全体や未使用の項目を渡さないことで、初期HTMLが大きく減ります。
2-2. CMS:トップページのテンプレートを点検する
- 「新着情報」「イベント」などのブロックで、表示件数の上限が「すべて」になっていないか。
- スライダーやバナーに、編集画面から貼り付けた画像がBase64のまま保存されていないか(WYSIWYGエディタに画像を貼り付けると起きやすい)。
- 過去のキャンペーン用の非表示ブロック(
display:none)が残っていないか。
3. 圧縮を有効にする(転送量の削減)
Apache
<IfModule mod_deflate.c>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
</IfModule>
</IfModule>
Apache 2.4では AddOutputFilterByType は mod_filter が提供するため、mod_filter が読み込まれていないと500エラーになります。上の例のように <IfModule mod_filter.c> で囲むか、モジュールの有効化を確認してください。
nginx
gzip on;
gzip_types text/css application/javascript application/json;
# text/htmlは既定で圧縮対象
IIS:「動的コンテンツの圧縮」「静的コンテンツの圧縮」機能を有効化します。
Vercel(Next.js):既定で圧縮されて配信されます。
圧縮は転送量を減らしますが、本診断の判定(非圧縮のサイズ)は変わりません。HTML自体の削減が本質的な対策です。
4. 確認方法(curl)
curl -sI https://www.city.example.lg.jp/ | grep -i '^content-length'
curl -s https://www.city.example.lg.jp/ | wc -c # 1000000以下が目標
軽量化の後はセキュリティAIチェッカーで再診断し、根拠欄のKB表示が約1MB以下になっていることを確認します。
サイトを壊さないための注意点(ガードレール)
- 画像を外部ファイル化する際は、
alt属性や表示順を維持し、アクセシビリティを損なわないよう確認してください。 - 全件データの削除で、JavaScriptの絞り込み機能や検索機能が動かなくなることがあります。代替(一覧ページへのリンク、サーバー側検索)を用意してから削除してください。
- 圧縮設定では、すでに圧縮済みの形式(画像、ZIP、PDF)を対象に含めないでください。CPU負荷が増えるだけで効果がありません。
よくある質問(FAQ)
HTMLのファイルサイズはどのくらいが目安ですか?
セキュリティAIチェッカーでは1,000,000バイト(約1MB)以下を ○ としています。これはHTML単体として明らかに大きく、Googlebotの2MB上限にも余裕を残すための経験的な目安です。一般的な自治体トップページのHTMLは数十〜数百KB程度に収まります。
gzipやbrotliで圧縮していれば問題ありませんか?
転送量は減りますが、ブラウザは展開後のHTMLを解析・描画するため端末の処理負荷は減りません。Googlebotのファイルサイズ上限も非圧縮のデータに適用されます。診断も非圧縮のサイズで判定するため、HTML自体の削減が本質的な対策です。
Googlebotは大きなHTMLをどこまで読みますか?
Google検索用のクロールでは、Googlebotはサポート対象ファイル形式の先頭2MB(PDFは先頭64MB)をクロールします。HTMLが2MBを超えると、それ以降の内容がインデックスされない可能性があります。
HTMLが重くなる主な原因は何ですか?
Base64で埋め込んだ画像、お知らせ・イベントの全件データの埋め込み、Next.jsの __NEXT_DATA__ やNuxtの __NUXT__ に渡した不要なデータ、肥大化したインラインCSS/JS、コメントアウトされた旧デザインや非表示の過去記事などが典型です。
過大な初期HTMLの診断では、画像やJavaScriptのサイズも含みますか?
含みません。評価対象は最初に返るHTML文書だけです。ページ全体の重さはLighthouse等で別途確認してください。Lighthouseはページ全体の転送量が5,000KiBを超えると指摘します。
なぜセキュリティ診断で初期HTMLのサイズを見るのですか?
脆弱性そのものではなく可用性・品質の補助指標です。災害時などアクセスが集中する場面で、1リクエストあたりの転送量が大きいとつながりにくくなります。また、表示に不要な全件データや非表示要素に、公開予定前の情報や内部向けメモが含まれていることもあります。
この項目を含む127項目を、URLを入れるだけで無料診断します。