コーポレートサイトの SEO チェックで、PageSpeed Insights(デスクトップ)に「レンダリングをブロックしているリクエスト」が出ました。推定される削減時間は 2,000ms です。

ユーザー補助・おすすめの方法・SEO はすでに 100 になっていたので、残るパフォーマンスに取り組みました。結果は次のとおりです。

指標 作業前 作業後(最良値)
パフォーマンス 55 76
First Contentful Paint 2.1秒 1.2秒
Largest Contentful Paint 3.4秒 2.8秒
Total Blocking Time 250ms 50ms
Speed Index 4.2秒 2.6秒
Cumulative Layout Shift 0.002 0.002

この記事では、効いた施策だけでなく、効かなかった施策と逆効果だった施策も、試した順に残します。前回までの施策は「PageSpeed Insightsスコアを改善」「WordPressのLCP・TBTを改善した施策」「WordPressのCLSを改善」にまとめています。今回はその続きです。

Webパフォーマンス改善:PageSpeed Insightsスコアを大幅に改善できた5つの施策 | CODE-PLUS(コードプラス) Webパフォーマンス改善:PageSpeed Insightsスコアを大幅に改善できた5つの施策 | CODE-PLUS(コードプラス) PageSpeed Insightsスコアを14から52に改善した実践的な手法を解説。document.write廃止、Critical CSS導入、優先度の低いCSSの遅延読み込み、requestIdleCallbackによるJS遅延読み込みなど...  続きを読む WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) CODE-PLUS(コードプラス)のお知らせ「WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策」です。  続きを読む WordPressのCLSが0.7→0に!パンくず・目次・プラグインが犯人だった話 | CODE-PLUS(コードプラス) WordPressのCLSが0.7→0に!パンくず・目次・プラグインが犯人だった話 | CODE-PLUS(コードプラス) PageSpeed InsightsのCLSが安定せず、教科書通りの画像サイズ指定やフォント対策では全く改善しない。パンくず・目次の遅延CSS、そしてContent Viewsプラグインの動的描画が真犯人でした。LiteSpeed Cacheに惑わ...  続きを読む

施策1:JS に defer を付ける(効果:小)

やったこと

defer を付けた JS は HTML の解析を止めず、解析が終わってから書いた順に実行されます。ライブラリ同士の実行順は変わりません。

defer にしてよいかは、ライブラリがいつ動き始めるかで決まります。CDN のファイルを1本ずつ開いて確かめました。

ライブラリ 動き始めるタイミング 判断
response-lazy(画像の出し分け) jQuery の ready、DOMContentLoaded defer にする
スクロールアニメーション DOMContentLoaded defer にする
アコーディオン DOMContentLoaded defer にする
Swiper 初期化は window の load で行っている defer にする
GSAP・ScrollTrigger DOMContentLoaded の後に refresh を呼ぶだけ defer にする
jQuery 本文のインラインスクリプトに $(function(){…}) がある そのまま

defer の JS は DOMContentLoaded より前に実行されるので、DOMContentLoaded や load を待って動くコードはそのまま動きます。一方、本文の途中に $(function(){…}) が直接書かれていると、その時点で jQuery が無いとエラーになります。jQuery だけは defer にできません。

<!-- jQuery:本文のインラインスクリプトが使うので defer にしない -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<!-- DOMContentLoaded で動くライブラリは defer -->
<script src="https://cdn.jsdelivr.net/npm/@sarap422/response-lazy@0.10.5/response.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/@sarap422/lib-scrollin@1.3.0/scrollin.min.js" defer></script>

あわせて、次の2つも読み込みをやめました。

  • jquery-migrate(5.6KiB)。全ページのインラインスクリプトとテーマの JS を調べ、.bind( や .size(、$.isArray( のような古い書き方が無いことを確かめた
  • 中身が 0 バイトの critical.min.css。空でもファイルの到着を待つので、コメントアウトした

結果

推定削減時間は 2,000ms から 1,850ms になっただけでした。

JS が一覧から消えても、CSS が19本残っています。ブラウザは CSS がそろうまで画面を描かないので、JS だけ外しても表示は早くなりません。


施策2:CSS を全部非同期にする(逆効果)

やったこと

CSS を非同期で読み込む定番の書き方は、media="print" で読み込んでおき、読み込みが終わったら all に切り替える方法です。印刷用の CSS は表示を止めないので、画面の描画を待たせずに済みます。

<link rel="stylesheet" href="style-utilities.min.css" media="print" onload='this.media="all"' />

<!-- JS が無効な環境向け -->
<noscript>
  <link rel="stylesheet" href="style-utilities.min.css" />
</noscript>

フォントの CSS 6本と、テーマの CSS 4本(カラーパレット2本、コンポーネント、ユーティリティ)に、この書き方を使いました。

結果

指標 施策1の後 CSS を全部非同期にした後
パフォーマンス 55 50〜51
First Contentful Paint 2.1秒 0.6秒
Total Blocking Time 250ms 1,690〜1,810ms
Speed Index 4.2秒 5.0〜5.3秒
Cumulative Layout Shift 0.002 0.041〜0.043

レンダリングブロックの推定削減時間は 160ms まで減り、FCP も 0.6秒に縮みました。それなのにスコアは下がっています。TBT が約7倍になったためです。

TBT が増えた理由

手元の Lighthouse でメインスレッドの内訳を見ると、一番重いのは「Style & Layout」(約1.5秒)でした。理由は2つ考えられます。

1つ目は、TBT の数え方です。TBT は FCP から後の重い処理だけを数えます。FCP が 2.1秒から 0.6秒に早まった分、前は FCP より前にあって数えられていなかった処理が、TBT に入るようになりました。処理そのものが増えたわけではありません。

2つ目は、非同期の CSS が届くたびに、ページ全体のスタイルを計算し直すことです。テーマの CSS は圧縮前で約740KB あり、それが4回に分かれて届くので、そのたびに計算し直しが走ります。CLS が 0.04 まで上がったのも、CSS が後から当たってレイアウトが動いたためです。


施策3:テーマの CSS を戻し、アイコンの CSS だけ非同期にする(効果:大)

やったこと

テーマの CSS とフォントの CSS は、元の読み込み方に戻しました。非同期のままにしたのは、アイコンフォントの CSS 2本だけです。

アイコンの CSS(material-symbols.min.css)は、3,400個以上のアイコンの指定を持つ約209KB(転送 29.7KiB)のファイルです。全ページを調べると、サイトで使っているアイコンは6個だけでした。少し遅れて出ても困らないので、非同期にしました。

<!-- アイコン:非同期 -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:wght,FILL@100..700,0..1" media="print" onload='this.media="all"' />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sarap422/font-material-symbols@1.0.0/material-symbols.min.css" media="print" onload='this.media="all"' />
<noscript>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:wght,FILL@100..700,0..1" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@sarap422/font-material-symbols@1.0.0/material-symbols.min.css" />
</noscript>

<noscript> の中には media="print" onload を付けません。<noscript> は JS が無効な環境でしか使われず、onload が動かないので、付けると CSS が適用されないままになります。

結果

指標 CSS を全部非同期にした後 アイコンだけ非同期
パフォーマンス 51 69
First Contentful Paint 0.6秒 1.2秒
Largest Contentful Paint 1.9秒 2.7秒
Total Blocking Time 1,810ms 190ms
Speed Index 5.3秒 3.3秒
Cumulative Layout Shift 0.043 0.002

FCP は 0.6秒から 1.2秒に戻りましたが、TBT と CLS が元の水準に戻り、スコアは 69 になりました。推定削減時間は、施策1の後の 1,850ms から 1,030ms に減っています。

CSS は、ページの形を決めるものは先に読み込み、遅れても見た目が崩れないもの(アイコン、印刷用、装飾用のフォント)だけを非同期にする、という線引きに落ち着きました。


施策4:使っていない GSAP を外す(効果:大)

やったこと

手元の Lighthouse で長いタスクを見ると、上位に GSAP と ScrollTrigger が並んでいました(189ms、113ms、77ms、68ms)。

トップページの本文と、トップで読み込むテーマの JS を調べると、GSAP を使っている箇所はありませんでした。使っていたのは、画像が読み込まれるたびに ScrollTrigger.refresh() を呼ぶ処理だけです。この refresh がページ全体のレイアウトを計算し直すので、使っていないのに重い処理だけが残っていました。

<?php if (is_front_page()) : ?>
  <!-- GSAP:トップでは使っていないので読み込まない -->
  <!-- <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js" defer></script> -->
  <!-- <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/ScrollTrigger.min.js" defer></script> -->
<?php endif; ?>

refresh を呼ぶための imagesLoaded も、全ページで読み込んでいました。こちらは GSAP を読み込むテンプレートだけで出すようにしました。

<?php if (is_page_template('templates/page-equipment.php')) : ?>
<script src="https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.min.js"></script>
<script>
  document.addEventListener('DOMContentLoaded', function() {
    if (!window.ScrollTrigger) return;
    imagesLoaded(document.querySelectorAll('img'), function() {
      ScrollTrigger.refresh();
    });
  });
</script>
<?php endif; ?>

imagesLoaded は、masonry やモーダル用のスライダーのパーツでも使っています。全ページを調べて、どのページにも置かれていないことを確かめてから条件を付けました。

結果

指標 アイコンだけ非同期 GSAP を外した後
パフォーマンス 69 76
Total Blocking Time 190ms 50ms
Speed Index 3.3秒 2.6秒

今回の施策の中では、これが一番効きました。テンプレートを使い回していると、ページによっては使わないライブラリも一緒に読み込まれがちです。ページごとに本当に使っているかを確かめる価値はあります。


施策5:ホワイトインを短くする(効果:なし)

やったこと

読み込み途中の画面(フィルムストリップ)を見ると、約2.7秒まで画面が真っ白でした。原因は、フォントの切り替わりやヘッダーのちらつきを隠すための白いオーバーレイです。初めて来た人には DOMContentLoaded の1秒後から、1.5秒かけて消える作りでした。

PageSpeed Insights は毎回「初めて来た人」として計るので、この演出の時間がそのまま Speed Index に乗ります。そこで、次のように短くしました。

箇所 前 後
オーバーレイが消え始めるまでの待ち(初回訪問) 1秒 0.5秒
オーバーレイが消える時間 1.5秒 1秒
ヘッダーのフェードイン(待ち/かける時間) 1秒/1秒 0.5秒/0.6秒

結果

2回計ってスコアは 55 と 71 で、効いたのかどうか判別できませんでした。

計測の揺れについて
ホワイトインを短くした後は、同じ状態のまま10分おきに計って、55 と 71 でした。16ポイントの差は、施策1つ分の効果より大きいことがあります。1回の計測で良し悪しを決めず、施策ごとに2回以上計ることをおすすめします。
XMRGRTX
一方、実際の利用者のデータ(CrUX、過去28日間)は、作業の前から LCP 1.3秒、INP 42ms、CLS 0.04 で、すべて「良好」でした。Google の評価に使われるのはこちらです。PageSpeed Insights のスコアは、改善箇所を探すための模擬計測として見るのがよいと思います。


残った課題

項目 内容 今回やらなかった理由
画像配信を改善する 推定 1,805KiB 画像を小さくすることは許可されていない
スライダーの画像 1枚目(LCP の画像)には fetchpriority="high" を付けているが、2〜8枚目もすぐに読み込まれ、回線を取り合っている Swiper のフェード効果では全スライドが同じ位置に重なるので、loading="lazy" では遅らせられない
テーマの CSS 「使用していない CSS」205KiB の大半がユーティリティとコンポーネント 投稿本文で使っているクラスを洗い出す必要があり、別の作業になる
キャッシュ保存期間 推定 305KiB 2回目以降の訪問にしか効かず、スコアには入らない

ここから先は、画像そのものに手を入れるか、テーマの CSS を作り直すかの段階になるので、今回の見直しはここで区切りました。


まとめ

施策 結果 スコア
JS に defer を付ける CSS が残っているので効果は小さい 55
CSS を全部非同期にする FCP は縮むが、TBT が約7倍になり逆効果 50〜51
アイコンの CSS だけ非同期にする TBT と CLS が戻る 69
使っていない GSAP を外す TBT 190ms → 50ms。効果:大 76
ホワイトインを短くする 計測の揺れに埋もれて判別できず 55〜71

今回わかったのは、次の3つです。

  • 「レンダリングをブロックしているリクエスト」の数字だけを減らしても、スコアは上がらない。ページの形を決める CSS まで非同期にすると、TBT と CLS が悪化する
  • 一番効果が大きいのは、使っていないライブラリを外すことだった。読み込み方を工夫するより、読み込まないほうが効く

関連記事

Webパフォーマンス改善:PageSpeed Insightsスコアを大幅に改善できた5つの施策 | CODE-PLUS(コードプラス) Webパフォーマンス改善:PageSpeed Insightsスコアを大幅に改善できた5つの施策 | CODE-PLUS(コードプラス) PageSpeed Insightsスコアを14から52に改善した実践的な手法を解説。document.write廃止、Critical CSS導入、優先度の低いCSSの遅延読み込み、requestIdleCallbackによるJS遅延読み込みなど...  続きを読む WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策 | CODE-PLUS(コードプラス) CODE-PLUS(コードプラス)のお知らせ「WordPressのLCP・TBTをプラグインのJS/CSS整理で改善した施策」です。  続きを読む WordPressのCLSが0.7→0に!パンくず・目次・プラグインが犯人だった話 | CODE-PLUS(コードプラス) WordPressのCLSが0.7→0に!パンくず・目次・プラグインが犯人だった話 | CODE-PLUS(コードプラス) PageSpeed InsightsのCLSが安定せず、教科書通りの画像サイズ指定やフォント対策では全く改善しない。パンくず・目次の遅延CSS、そしてContent Viewsプラグインの動的描画が真犯人でした。LiteSpeed Cacheに惑わ...  続きを読む 画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) 画像のアスペクト比を自動計算・付与する | aspect-ratioが効かない原因とCLS対策 | CODE-PLUS(コードプラス) CSS aspect-ratioが効かない原因を押さえつつ、投稿保存時に実画像からアスペクト比(縦横比)を自動計算・自動付与し、SP/PCの出し分けまで手作業ゼロで維持する仕組み、CLS対策として無理なく運用するための実運用での使い方を解説します。  続きを読む

参考リンク