418 KB削っても本丸は別だった。LCPの55%を占めたTTFBと5分CDNキャッシュ

WordPressの不要ファイルを418 KB減らした後、実ユーザーLCP 2.9秒のうちTTFBが1.6秒と判明。CDNの5分キャッシュ、HITとMISSの約3倍差、画像がキャッシュされない問題を実測から整理します。

WordPressの軽量化後に見えたTTFB 1.6秒と、5分間のCDNキャッシュ、HITとMISSの計測例を示す日本人女性

WordPressのCSS、JavaScript、フォントを調べ、1ページあたり427,918バイト減らしました。ところがPageSpeed Insightsの実ユーザーデータを見ると、LCP 2.9秒のうちTTFBが1.6秒。ページの中身を受け取る前の待ち時間が55%を占めていました。容量削減とは別に、CDNキャッシュを調べる必要がありました。

まず1ページあたり約418 KB減らした

2026年9月21日に行った軽量化は次の4項目です。

作業削減量
子テーマ style.css の二重読み込み解消13,324 B
テーマ書体・絵文字・jquery-migrateの停止119,802 B
Envo Extraの停止93,432 B
Font AwesomeのSVG置き換え201,360 B
合計427,918 B(約418 KB)

CSSは27本から23本、JavaScriptは18本から16本、ローカルのwoff2フォントは5本から0本になりました。

これは無意味な削減ではありません。同じサーバーから、削減量とほぼ同じ436,628 Bの実ファイル6本をHTTP/2で並列取得すると、光回線でも0.38〜0.85秒かかりました。Lighthouseのモバイル設定に近い1.6 Mbpsなら、単純計算で約2.1秒です。

ただし、ここで「サイトが何秒速くなった」とは言えません。実際の表示時間には、サーバー応答、HTML解析、CSS、JavaScript、画像、端末性能などが重なっているからです。

実ユーザーLCP 2.9秒のうちTTFBが1.6秒

作業当日にPageSpeed Insightsで取得した、モバイルのフィールドデータは次のとおりでした。

指標値
LCP2.9秒
FCP2.9秒
TTFB1.6秒
CLS0

TTFBは、ページへアクセスしてから最初の1バイトが届くまでの時間です。HTML、CSS、画像がどれだけ小さくても、その前に1.6秒待っていれば、後に続くFCPやLCPも早く始まりません。

web.devでは、多くのサイトが目安として0.8秒以下を目指すよう案内しています。1.6秒は「改善が必要」の帯です。TTFBはCore Web Vitalsそのものではありませんが、後続の指標すべての土台になります。

今回減らした418 KBは、最初の1バイトが到着した後の転送や描画に効くものです。TTFB 1.6秒を直接縮める作業ではありません。

手元ではTTFBが291ミリ秒だった

ところが、自宅の光回線から複数回測るとTTFBは194〜440ミリ秒で、中央値は291ミリ秒でした。PageSpeed Insightsの実ユーザーデータ1.6秒とは大きな差があります。

同じサイトなのに差が出る理由を調べると、レスポンスヘッダーに次の指定がありました。

cache-control: s-maxage=300

s-maxage はCDNなどの共有キャッシュに対する保持時間です。300秒なので、キャッシュは5分で古くなります。

さくらのレンタルサーバの公式サポートにも、コンテンツブーストの初期キャッシュ時間は s-maxage=300 とあります。僕のサイトで観測した値と一致しました。

キャッシュMISSはHITの約3倍かかった

同じ記事を続けて取得し、CDNの x-cache とTTFBを比べました。

記事x-cacheTTFB
記事A・1回目MISS0.853秒
記事A・2回目HIT0.290秒
記事B・1回目MISS1.006秒
記事B・2回目HIT0.331秒

キャッシュが当たれば約0.3秒ですが、外れると0.85〜1.0秒でした。MISS時はCDNがオリジンのWordPressへ取りに行き、PHPなどの処理を待つためです。

このサイトには1,295本の記事があり、流入は検索が中心です。ある記事に5分以内に次のアクセスが来なければ、次もMISSになる可能性があります。

実際のMISS率をアクセスログで集計したわけではないため、「多くの訪問がMISSになっている」は現時点では推測です。ただし、5分という設定、MISSとHITの実測差、CrUXのTTFB 1.6秒は、同じ方向を示しています。

画像には private が付き、CDNに載っていなかった

さらに、HTML、CSS、JavaScriptと画像でキャッシュ指定が違うことも分かりました。

種類Cache-Control観測した動作
HTMLs-maxage=300CDNで5分
CSS / JSmax-age=604800, s-maxage=300ブラウザ7日、CDN5分
画像private, max-age=2592000CDNは毎回MISS

HTTPキャッシュの仕様では、private が付いたレスポンスは共有キャッシュへ保存できません。実際、同じ画像を繰り返し取得しても x-cache: MISS、age: 0 のままでした。

一方、WebP変換自体は機能しています。同じURLへ Accept: image/webp を付けると、JPEG 94,380 BではなくWebP 69,938 Bが返り、約26%小さくなりました。

確認できている事実は、次の3点です。

  • Accept に応じてJPEGとWebPを出し分けている
  • レスポンスには Vary: Accept と Cache-Control: private が付く
  • 画像はCDNで毎回MISSになる

WebP変換プラグインの出し分け処理が private の発生に関係している可能性は高いものの、原因プラグインはまだ特定できていません。ここは確定事項ではなく、次の調査対象です。

次にやることの順番が変わった

軽量化を始めたときは、ファイル容量を減らすことが中心でした。しかし実測後の優先順位は変わりました。

優先施策期待する効果
1画像の private の原因特定画像をCDNへ載せられる可能性
2s-maxage 延長の検討HTMLのHIT率を上げ、TTFBを短縮
3gzip圧縮の解決HTML 166 KBを約36 KBへ縮小する見込み
4レンダリングブロックCSSの整理Lighthouseが示す待ち時間を短縮
5不要アセット削減427,918 B削減済み

ただし、キャッシュ時間を長くすれば無条件に良いわけではありません。更新後の内容が古いまま残る時間も長くなります。画像の出し分けを残すなら、CDNが Vary: Accept を正しく扱えるかも確認が必要です。

設定を変更する前に、s-maxage=300 の出どころ、画像へ private を付ける処理、キャッシュ削除の方法を特定します。そのうえで、HIT/MISS、WebPの出し分け、更新内容の反映を再測定します。

容量と待ち時間は、別々に測る

427,918 B減らしたことは、転送量とファイル数を確実に減らしました。特にフォント181 KBはgzipでも減らせないため、読み込まないようにした意味があります。

一方、LCPの前半を占めていたTTFBは別の問題です。418 KBを削ったからといって、サーバーが最初の1バイトを返すまでの1.6秒が直接短くなるわけではありません。

今回の収穫は「高速化できた」と言い切れる数字より、次に調べる場所が分かったことでした。容量、リクエスト数、TTFB、キャッシュHIT率を分けて測ると、同じ「遅い」の中に違う原因が見えてきます。

参考リンク

参考になったらブログランキングを1回だけ押してもらえると助かります。
(1日1回でOK/匿名のまま応援できます)

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

トップへ戻る