Web高速化の最前線|遅延読み込み(Lazy Load)・コード圧縮・INP対策でLighthouseスコア90点超えを狙う
ページ表示が1〜3秒に伸びると直帰率が32%高まる──Google/SOASTAの2017年調査が示すように(モバイル実測値)、「体感の速さ」はコンバージョンの前提条件です。
しかも2025年の今、“速さ”は単なるUX改善ではなく、検索評価を左右する〈Core Web Vitals〉のスコアそのもの。
この記事では遅延読み込み(Lazy Load)とコード圧縮を中心に、Lighthouseスコアを即日底上げする実践テクニックを解説します。
Core Web Vitals最新事情──INP時代の3本柱
2024年3月のアップデート以降、主要指標はLCP・CLS・INPの3つです。INP(Interaction to Next Paint)はページ全体の相互作用レイテンシーを評価し、200 ms未満が“良好”の目安。
旧指標FIDはタップやクリックの初動しか測れませんでしたが、INPは「ページ滞在中で最も遅い操作」を拾うため、JavaScript実行時間とレンダリング負荷を同時に最適化する必要があります。
ページ冒頭で不要なスクリプトを遅延ロードし、メインスレッドをブロックしない設計がこれまで以上に重要です。
参考:web.dev | INP が FID の後継指標になった理由
遅延読み込み(Lazy Load)の原理と最新ブラウザ対応
Lazy Loadは「ビューポートに入る直前まで通信を遅らせる」ことで初期表示を軽くする手法です。2025年5月現在、loading="lazy"
はChrome 76・Edge 79・Firefox 75・Safari 15.4・Opera 64以降、ほぼすべての主要ブラウザが標準サポート済み。
WordPress 6.4以降は画像に自動付与されますが、ヒーロー画像まで遅延するとLCPが悪化するため、ファーストビュー要素にはloading="eager"
または属性省略で即時ロードに切り替えましょう。
ネイティブloading=”lazy”属性の使い方
基本形:
<img src="team.webp" alt="チーム写真" width="600" height="400" loading="lazy">
Chromeの実装では「ビューポート+1画面」でプリロードが走るため、ユーザーが高速スクロールしても白抜けが起きにくい設計です。
YouTube iframeや広告タグにもloading="lazy"
が効くため、CLS改善にもつながります。
Intersection ObserverによるカスタムLazy Load
スクロール速度や“手前読み”距離を柔軟に調整したいならIntersection Observerを使います。
// 遅延読み込み対象の画像をすべて取得
const lazyImages = document.querySelectorAll('[data-src]');
// IntersectionObserverのインスタンスを作成
const io = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// ビューポートに入ったらdata-srcをsrcに置き換え
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
// 監視を解除してパフォーマンス向上
obs.unobserve(img);
}
});
}, { rootMargin: '200px' }); // 200px手前で先読み
// 各画像にObserverを登録
lazyImages.forEach(img => io.observe(img));
rootMargin
を広げるほど事前ダウンロードが早まり、UIの“チラ見え”を防げます。Reactならカスタムフック化し、SSR時はクライアントのみでobserverを生成することを忘れずに。
コード圧縮&Tree Shaking──実バイト数を削る王道
Lighthouseの「Reduce JavaScript Execution Time」が赤字なら、まずビルド時にMinify+Tree Shakingを有効化しましょう。
Webpack 5/Esbuild/Viteはいずれもproductionモードで自動的にTerserが走り、未使用exportが除去されます。
Google PageSpeed Insights公式デモでは、同一SPAをミニファイ前767 KB→62 KB(gzip)に削減し、TTIを42%短縮した事例が示されています。
さらに<script type="module">
+nomodule
フォールバックでモダンブラウザ専用バンドルを分離し、初回ダウンロードを最低限に。
Brotli/Gzipで転送サイズを最小化
Brotli圧縮はGzip比で20〜30%優位ですが、サーバーモジュールが前提です。Apache 2.4ならmod_brotli
をロードし、設定例は:
<IfModule brotli_module>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript
BrotliCompressionQuality 5
BrotliMinLength 1024 # 1KB以上のファイルのみ圧縮(極小ファイルには非推奨)
</IfModule>
Nginx公式ビルドには含まれていないため、ngx_brotli
をソースコンパイルするか、OpenResty系ディストリを採用します。
※もし導入が難しい場合は、CloudflareやFastlyなどのCDNサービスを利用すれば、Brotli圧縮を簡単に有効化できます。既存サーバー構成を変えずに済むため、運用ハードルも下がります。
Cache-Control: public, max-age=31536000, immutable
を併用すれば再訪問時はTLSネゴシエーションを省略でき、Core Web Vitalsの「Network Round Trips」節約に直結します。
Lighthouse計測とfetchpriority=”high”の活用
最適化後はChrome DevToolsのLighthouseを再実行し、モバイルPerformance 90点超えを目標に。「Opportunities」の節約時間合計がゼロ近くなら合格です。
なおChrome 101/Edge 101以降はfetchpriority="high"
属性で重要リソースの優先度を上げられますが、Firefox・Safari(TP版のみフラグ対応)は未サポートです。
非対応ブラウザでは無視されるだけなので、フォールバック処理は不要ですが、“多用し過ぎると逆効果”という点は覚えておきましょう。
複数の画像・スクリプトすべてに指定すると、ブラウザの優先度制御が機能しにくくなり、かえってLCPが悪化することがあります。
重要なのは「LCPに寄与するメイン画像やヒーロー要素など、本当に優先表示すべきリソース」に絞って使うことです。
参考:MDN | fetchpriority属性のブラウザ対応
HTTP/HTTPSとは?ステータスコード・ヘッダー・TLSの仕組み
まとめ:今日から“赤字”を緑に変えよう
Core Web Vitalsは毎年進化していますが、ユーザーの体感はシンプル──“サクサク動くサイトが好き”。
Lazy Loadで初期転送を削り、Minify+Brotliで実バイト数を圧縮し、LighthouseでBefore/Afterを可視化する。
この3ステップを回すだけで、ページは確実に速くなり、INP・LCP・CLSすべてが改善します。デザインやコンテンツを磨く前に「速さ」を整えれば、読者のエンゲージメントも検索順位もあとから自然と付いてくるはずです。