レンダリングが遅延する原因と改善方法を解説!

レンダリングが遅延する原因と改善方法を解説!

レンダリング遅延は、Webサイトのユーザー体験とSEO評価に大きく影響する重要な要素です。

ページの読み込み速度が遅いと、ユーザーの離脱率が上昇し、検索エンジンの順位も低下します。

本記事では、レンダリング遅延の原因を詳しく解説し、CSS・JavaScriptの最適化、画像の遅延読み込み、CDNの活用など、具体的な改善方法を実践的に紹介します。

レンダリング遅延とは?

レンダリング遅延とは、Webページがブラウザに表示されるまでにかかる時間的な遅れのことを指します。

ユーザーがURLにアクセスしてから、実際にコンテンツが画面に描画されるまでの一連のプロセスで発生する遅延を意味します。

具体的には、HTMLの解析、CSSスタイルの適用、JavaScriptの実行、画像やフォントなどのリソース読み込みといった複数の処理段階で遅延が生じます。

特に、レンダリングをブロックするリソース(render-blocking resources)の存在や、大容量のファイル、非効率なコードなどが主な原因となります。

この遅延は、First Contentful Paint(FCP)やLargest Contentful Paint(LCP)といったCore Web Vitalsの指標で測定され、Googleの検索ランキング要因にも含まれています。

レンダリング遅延が長いと、ユーザーは「ページが重い」と感じ、離脱率の増加やコンバージョン率の低下につながるため、Webサイト運営において改善すべき重要な課題です。

補足記事

レンダリング遅延の目安は?平均はどのくらい?

指標

良好

改善が必要

不良

説明

FCP (First Contentful Paint)

1.8秒以下

1.8〜3.0秒

3.0秒超

最初のコンテンツが表示されるまでの時間

LCP (Largest Contentful Paint)

2.5秒以下

2.5〜4.0秒

4.0秒超

最大のコンテンツ要素が表示されるまでの時間

TTI (Time to Interactive)

3.8秒以下

3.8〜7.3秒

7.3秒超

ページが完全に操作可能になるまでの時間

レンダリング遅延の目安は、Googleが定めるCore Web Vitalsを基準に評価されます。業界平均では、モバイルサイトのLCPは約3.5〜4.0秒、デスクトップでは2.5〜3.0秒程度とされています。

特に重要なのがLCP(Largest Contentful Paint)で、Googleは2.5秒以下を「良好」と評価しています。

これはページの主要コンテンツがユーザーに表示される速度を示し、SEOランキングに直接影響します。

業界別では、Eコマースサイトの平均LCPは約3.7秒、ニュースサイトは約3.2秒、ブログは約2.8秒となっています。

モバイルデバイスでは通信環境の影響でデスクトップより1.5〜2倍遅くなる傾向があります。

目標としては、全デバイスでLCP 2.5秒以下、FCP 1.8秒以下を目指すことが推奨されます。これにより、ユーザー体験の向上と検索順位の改善が期待できます。

補足記事

レンダリング遅延が発生する原因

レンダリング遅延は、複数の要因が複合的に作用して発生します。以下、主要な原因を詳しく解説します。

レンダリングブロックリソース

CSSやJavaScriptファイルは、ブラウザのレンダリングプロセスを一時停止させる最大の原因です。

特に、<head>タグ内に配置された大容量のCSSファイルや、asyncdefer属性のないJavaScriptは、HTMLの解析とレンダリングを完全にブロックします。

外部スタイルシートが読み込まれるまで、ブラウザは画面に何も表示できません。

レンダリングブロックとは?

大容量の画像・メディアファイル

最適化されていない高解像度画像は、レンダリング遅延の大きな要因です。

特に、ファーストビュー(初期表示領域)に配置された数MBの画像は、LCPスコアを著しく悪化させます。

適切な圧縮や次世代フォーマット(WebP、AVIF)への変換が行われていない場合、ダウンロード時間が長くなります。

サーバーレスポンスの遅延(TTFB)

Time to First Byte(TTFB)が長いと、ブラウザがHTMLを受信し始めるまでの時間が延びます。

サーバーの処理能力不足、データベースクエリの非効率性、ホスティング環境の品質低下などが原因となります。

特に共有サーバーや低スペックのホスティングでは顕著です。

過剰なHTTPリクエスト

Webページが多数のリソース(CSS、JavaScript、画像、フォントなど)を個別に読み込む場合、HTTPリクエスト数が増加します。

各リクエストには接続確立のオーバーヘッドがあり、特にHTTP/1.1では同時接続数に制限があるため、順次読み込みによる遅延が発生します。

JavaScriptの実行時間

重いJavaScript処理は、メインスレッドを占有してレンダリングを遅延させます。

特に、DOM操作が多い複雑なスクリプト、サードパーティ製の分析ツールやチャットウィジェット、未最適化のフレームワークコードなどが原因となります。

Webフォントの読み込み

カスタムWebフォントは、FOIT(Flash of Invisible Text)やFOUT(Flash of Unstyled Text)を引き起こし、テキストの表示を遅延させます。

特に複数のフォントファミリーや太さのバリエーションを読み込む場合、遅延が顕著になります。

CDNの未使用・地理的距離

CDN(Content Delivery Network)を使用していない場合、ユーザーとサーバー間の物理的距離によってレイテンシが増加します。

日本のユーザーが海外サーバーにアクセスする場合、往復の通信時間だけで数百ミリ秒の遅延が発生します。

CDNとは?

ブラウザキャッシュの未設定

適切なキャッシュポリシーが設定されていないと、リピート訪問時でも全リソースを再ダウンロードする必要があります。

Cache-ControlヘッダーやETagの設定不備により、不要な通信が繰り返されます。

CSSの複雑性と未使用スタイル

大量の未使用CSSルールや、深くネストされた複雑なセレクタは、ブラウザのスタイル計算を遅延させます。

特に、CSSフレームワーク全体を読み込んでいるが実際には一部しか使用していない場合、無駄な処理が発生します。

サードパーティスクリプトの影響

広告、アクセス解析、SNS連携ボタンなど、外部サービスのスクリプトは制御が困難です。

これらのスクリプトが遅延すると、ページ全体のレンダリングに影響を与えます。特に、同期的に読み込まれるスクリプトは致命的です。

モバイルデバイスの処理能力

低スペックのモバイルデバイスでは、CPUやメモリの制約により、JavaScript実行やレンダリング処理が遅くなります。

デスクトップで最適でも、モバイルでは大幅に遅延する可能性があります。

リダイレクトチェーン

複数のリダイレクト(例:http → https → www付きURL)が連鎖すると、各段階でHTTPリクエスト・レスポンスのラウンドトリップが発生し、初期表示が遅延します。

これらの原因を特定し、優先順位をつけて対策することが、効果的なレンダリング遅延の改善につながります。

レンダリング遅延を改善する方法

レンダリング遅延を効果的に改善するには、原因を特定し、適切な技術と手法を体系的に適用することが重要です。

以下、具体的な改善方法を実践的に解説します。

JavaScriptの非同期化・遅延実行

JavaScriptは、asyncまたはdefer属性を使用して非同期に読み込むことで、HTMLパースをブロックしないようにします。

<!-- async: ダウンロード完了次第すぐに実行(実行順序は保証されない) -->
<script async src="analytics.js"></script>

<!-- defer: HTMLパース完了後に実行(記述順に実行) -->
<script defer src="app.js"></script>

<!-- type="module"は自動的にdefer動作 -->
<script type="module" src="main.js"></script>

asyncは、Google Analytics などの独立した機能に適しています。

deferは、DOM操作が必要なスクリプトや、他のスクリプトに依存するコードに適しています。

JavaScript バンドルの分割(code splitting)も重要です。

Webpack、Rollup、Parcel などのモジュールバンドラーを使用して、初期ロードに必要なコードと、後で読み込めるコードを分離します。

// 動的インポートによる遅延読み込み
button.addEventListener('click', async () => {
  const module = await import('./heavy-feature.js');
  module.init();
});

React では React.lazy、Vue では defineAsyncComponent を使用して、コンポーネント単位で遅延読み込みを実装できます。

コード分割(Code Splitting)

必要なコードだけを初期ロードし、残りは必要に応じて動的に読み込みます。

// Webpack動的インポート
const loadChart = () => import(/* webpackChunkName: "chart" */ './chart.js');

button.addEventListener('click', async () => {
  const chart = await loadChart();
  chart.render(data);
});

Tree Shaking

使用されていないコードを削除してバンドルサイズを削減します。ES6モジュール形式で記述し、Webpack、Rollup、Parcelなどのバンドラーを使用します。

// 必要な関数だけインポート
import { map, filter } from 'lodash-es'; // lodash全体ではなく個別関数

// 不要なコードは削除される

Minification(圧縮)と難読化

Terser、UglifyJS、esbuildなどのツールでコードを圧縮し、ファイルサイズを削減します。

// 圧縮前
function calculateTotal(items) {
  let total = 0;
  for (let i = 0; i < items.length; i++) {
    total += items[i].price;
  }
  return total;
}

// 圧縮後
function calculateTotal(t){let e=0;for(let l=0;l<t.length;l++)e+=t[l].price;return e}

Web Workersの活用

重い処理をメインスレッドから分離し、バックグラウンドで実行します。

// worker.js
self.addEventListener('message', (e) => {
  const result = heavyComputation(e.data);
  self.postMessage(result);
});

// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.addEventListener('message', (e) => {
  console.log('結果:', e.data);
});

デバウンス・スロットリング

頻繁に発火するイベント(scroll、resize、input)の処理回数を制限します。

Copy// デバウンス:最後のイベントから一定時間後に1回実行
function debounce(func, wait) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

// 使用例
const handleSearch = debounce((query) => {
  fetchResults(query);
}, 300);

input.addEventListener('input', (e) => handleSearch(e.target.value));

RequestAnimationFrame の使用

DOM更新やアニメーションは、requestAnimationFrameを使用してブラウザの描画サイクルに同期させます。

Copyfunction animate() {
  // アニメーション処理
  element.style.transform = `translateX(${position}px)`;
  
  if (animating) {
    requestAnimationFrame(animate);
  }
}

requestAnimationFrame(animate);

JavaScriptの速度改善方法の記事も是非参考にしてください。

CSSの最適化

CSSはレンダリングブロックリソースであるため、最優先で最適化する必要があります。

まず、ファーストビュー(above the fold)に必要な最小限のCSSを<head>タグ内にインライン化します。

これにより、外部CSSファイルのダウンロードを待たずに、重要なコンテンツをすぐに表示できます。

<head>
  <style>
    /* クリティカルCSS:ファーストビューに必要な最小限のスタイル */
    body { margin: 0; font-family: sans-serif; }
    .header { background: #333; color: white; padding: 20px; }
    .hero { height: 400px; background: #f0f0f0; }
  </style>
  
  <!-- 非クリティカルCSSは遅延読み込み -->
  <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>

クリティカルCSSの抽出には、Critical、PurgeCSS、UnCSS などのツールを使用できます。

これらは、HTMLを解析して実際に使用されているCSSルールのみを抽出します。

また、未使用CSSの削除も重要です。Chrome DevToolsのCoverageタブを使用すると、どのCSSルールが実際に使用されているかを確認できます。

Bootstrap などのフレームワークを使用している場合、実際に使用しているクラスのみを含むカスタムビルドを作成することで、ファイルサイズを70〜80%削減できることがあります。

CSSファイルの分割も効果的です。す

べてのページで共通のベーススタイルと、特定のページでのみ必要なスタイルを分離し、必要なページでのみ追加のCSSを読み込むようにします。

リソースの優先順位付け

Resource Hints を使用して、ブラウザに重要なリソースの優先度を伝えます。

<!-- DNS Prefetch: DNSルックアップを事前実行 -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com">

<!-- Preconnect: DNS + TCP + TLS接続を事前確立 -->
<link rel="preconnect" href="https://cdn.example.com">

<!-- Prefetch: 将来必要になる可能性のあるリソースを低優先度で取得 -->
<link rel="prefetch" href="next-page.html">

<!-- Preload: 現在のページで確実に必要なリソースを高優先度で取得 -->
<link rel="preload" href="hero-image.jpg" as="image">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

特に、LCP要素となる画像やWebフォントに対してpreloadを使用すると、表示速度が大幅に改善されます。

ただし、過度な使用は逆効果なので、本当に重要なリソース(2〜3個程度)に限定します。

画像の最適化と次世代フォーマットの採用

画像は多くのWebページで最大のデータ量を占めるため、最適化の効果が非常に大きくなります。

次世代画像フォーマットの使用

WebPとAVIFは、JPEGやPNGと比較して同じ視覚品質で30〜50%小さいファイルサイズを実現します。

<picture>
  <!-- 最新ブラウザ向けにAVIF -->
  <source srcset="image.avif" type="image/avif">
  <!-- AVIF非対応ブラウザ向けにWebP -->
  <source srcset="image.webp" type="image/webp">
  <!-- フォールバック用にJPEG -->
  <img src="image.jpg" alt="説明" loading="lazy">
</picture>

変換には、Squoosh、ImageMagick、cwebp(WebP用)、avifenc(AVIF用)などのツールを使用できます。

次世代フォーマット画像について詳しくはこちら

レスポンシブ画像の実装

デバイスの画面サイズに応じて最適なサイズの画像を配信することで、無駄なデータ転送を削減します。

<img 
  src="image-800w.jpg" 
  srcset="image-400w.jpg 400w,
          image-800w.jpg 800w,
          image-1200w.jpg 1200w,
          image-1600w.jpg 1600w"
  sizes="(max-width: 600px) 100vw,
         (max-width: 1200px) 50vw,
         800px"
  alt="説明"
  loading="lazy">

srcset属性で複数サイズの画像を用意し、sizes属性でブレークポイントごとの表示サイズを指定します。ブラウザは自動的に最適な画像を選択します。

レスポンシブ画像について詳しくはこちら

画像の遅延読み込み(Lazy Loading)

ファーストビューに表示されない画像は、遅延読み込みすることで初期ロード時間を短縮します。

<!-- ネイティブ遅延読み込み -->
<img src="image.jpg" loading="lazy" alt="説明">

<!-- iframeにも適用可能 -->
<iframe src="video.html" loading="lazy"></iframe>

ネイティブのloading="lazy"属性は、主要ブラウザで広くサポートされています。

ただし、LCP要素となる可能性のあるファーストビュー画像には使用しないでください。

JavaScript ライブラリ(lazysizes、lozad.js)を使用すると、より細かい制御が可能です。

Intersection Observer API を使用したカスタム実装も一般的です。

const imageObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      img.classList.remove('lazy');
      observer.unobserve(img);
    }
  });
});

document.querySelectorAll('img.lazy').forEach(img => {
  imageObserver.observe(img);
});

画像の遅延読み込みについて詳しくはこちら

画像の圧縮

画像の圧縮は、視覚品質を保ちながらファイルサイズを削減する重要な最適化手法です。

ロスレス圧縮とロッシー圧縮の2種類があり、写真にはJPEG品質85〜90%のロッシー圧縮が効果的で、30〜50%のサイズ削減が可能です。

TinyPNG、ImageOptim、Squooshなどのツールを使用すると簡単に圧縮できます。

また、次世代フォーマットのWebPやAVIFに変換することで、従来のJPEG/PNGと比較してさらに30〜50%小さくなります。適切な圧縮により、ページ読み込み速度が大幅に向上し、LCPスコアの改善とSEO評価の向上につながります。

適切な画像サイズ

実際の表示サイズの2倍程度(Retina対応)の画像を用意するのが一般的です。

例えば、400px幅で表示する場合、800px幅の画像を用意します。

それ以上大きくしても、視覚的な改善はほとんどなく、ファイルサイズだけが増加します。

CDN経由での画像配信

Cloudinary、Imgix、ImageKitなどの画像CDNサービスを使用すると、URLパラメータで動的にリサイズ・圧縮・フォーマット変換が可能です。

<!-- Cloudinaryの例:自動最適化 -->
<img src="https://res.cloudinary.com/demo/image/upload/w_800,f_auto,q_auto/sample.jpg">

f_autoは最適なフォーマット(WebP、AVIF)を自動選択し、q_autoは最適な品質を自動設定します。

サーバーサイドの最適化

サーバーサイドキャッシュの実装

サーバーサイドキャッシュは、動的に生成されるページやデータベースクエリの結果を保存し、再利用することでサーバー処理時間を劇的に短縮する技術です。

WordPressではWP Super CacheやW3 Total Cacheなどのプラグインで静的HTMLを生成し、毎回のPHP実行とデータベースアクセスを回避できます。

カスタムアプリケーションでは、RedisやMemcachedなどのメモリベースキャッシュを使用すると、ミリ秒単位の高速応答が可能になります。

適切に実装すれば、TTFB(Time to First Byte)を数秒から数十ミリ秒に改善でき、サーバー負荷も大幅に削減されます。キャッシュ有効期限の設定も重要で、更新頻度に応じて最適な期間を設定します。

// PHPでのRedis使用例
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$cacheKey = 'page:' . $pageId;
$html = $redis->get($cacheKey);

if (!$html) {
    $html = generatePageHTML($pageId);
    $redis->setex($cacheKey, 3600, $html); // 1時間キャッシュ
}

echo $html;

データベースの最適化

データベースの最適化は、クエリ実行速度を改善し、サーバー応答時間を短縮する重要な施策です。

最も効果的なのはインデックスの追加で、WHERE句やJOIN条件で使用される列にインデックスを設定すると、検索速度が数十倍から数百倍向上します。

N+1クエリ問題の解消も重要で、ループ内で個別クエリを実行する代わりに、JOINや一括取得で1回のクエリにまとめます。

不要なSELECT *を避け、必要な列のみを取得することでデータ転送量を削減します。

また、クエリキャッシュやコネクションプーリングの活用、定期的なテーブル最適化(OPTIMIZE TABLE)も効果的です。

データベース最適化について詳しく

PHP/サーバーサイド言語の最適化

PHP/サーバーサイド言語の最適化は、サーバー処理速度を向上させる重要な施策です。

最も効果的なのはOPcache(PHPバイトコードキャッシュ)の有効化で、スクリプトのコンパイル時間を省略し、実行速度が2〜3倍向上します。

PHP 5.5以降は標準搭載されており、設定ファイルで有効化するだけです。

また、最新バージョンへのアップグレードも重要で、PHP 8.xはPHP 7.xより20〜30%高速で、さらに多くの最適化機能を搭載しています。

不要なプラグインやモジュールの無効化、効率的なコーディング(ループの最適化、不要な処理の削減)、オートローダーの活用も効果的です。

HTTP/2またはHTTP/3の有効化

HTTP/2は多重化、ヘッダー圧縮、サーバープッシュなどの機能により、HTTP/1.1より高速です。

HTTP/3はさらに低レイテンシを実現します。

ほとんどのモダンなWebサーバー(Apache 2.4.17+、Nginx 1.9.5+)とCDNがHTTP/2をサポートしています。SSL/TLS(HTTPS)が必須です。

参考:HTTP/3とは?HTTP/2の違いや特徴を比較

Gzip/Brotli圧縮の有効化

テキストベースのリソース(HTML、CSS、JavaScript、SVG、JSON)を圧縮して転送サイズを削減します。

# Apache .htaccess
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
# Nginx設定
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1000;

Brotli圧縮はGzipより15〜20%高い圧縮率を実現しますが、サーバー設定が必要です。

CDNの活用

CDN(Content Delivery Network)は、世界中に分散配置されたエッジサーバーからコンテンツを配信し、ユーザーに最も近いサーバーから高速にデータを提供する仕組みです。

物理的な距離が短縮されるため、TTFB(Time to First Byte)が劇的に改善され、特に海外ユーザーへの配信で効果が顕著です。

Cloudflare、Amazon CloudFront、Fastlyなどの主要サービスがあり、Cloudflareは無料プランも提供しています。

CDN導入の効果

静的リソース(画像、CSS、JavaScript)だけでなく、HTMLもキャッシュ可能で、オリジンサーバーの負荷を大幅に軽減します。

さらに、HTTP/2やBrotli圧縮などの最新技術にも対応し、DDoS攻撃からの保護機能も備えています。

グローバル展開するWebサイトには必須の技術です。

設定のベストプラクティス

静的リソース(画像、CSS、JavaScript)は長期キャッシュ(1年)、HTMLは短期キャッシュ(1時間〜1日)に設定します。

Cache-Control: public, max-age=31536000, immutable  # 静的リソース
Cache-Control: public, max-age=3600                  # HTML

キャッシュバスティング戦略として、ファイル名にハッシュ値を含めます(例:app.abc123.js)。

参考記事:CDNとは?

Webフォントの最適化

Webフォントの最適化は、テキスト表示の遅延を防ぎ、FCPとLCPを改善する重要な施策です。

font-displayプロパティの使用

最も効果的なのはfont-display: swapの設定で、Webフォント読み込み中もフォールバックフォントでテキストをすぐに表示し、FOIT(テキストの非表示)を回避できます。

@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2');
  font-display: swap; /* FOIT回避、すぐにフォールバックフォントで表示 */
}

font-displayの値


ブロック期間

スワップ期間

動作説明

推奨用途

swap

なし(0ms)

無制限

すぐにフォールバックフォントで表示し、Webフォント読み込み後に切り替え。テキストが常に表示される

一般的なWebサイト(最推奨)

block

短時間(最大3秒)

無制限

Webフォント読み込み中はテキストを非表示にし、読み込み後に表示。FOIT発生

ブランドロゴなど、特定フォントが必須の場合のみ

fallback

極短時間(約100ms)

短時間(約3秒)

100ms以内に読み込めない場合はフォールバックフォントで表示。3秒以内に読み込めればWebフォントに切り替え、それ以降はフォールバックのまま

パフォーマンス重視だが、可能な限りWebフォントを使いたい場合

optional

極短時間(約100ms)

なし

100ms以内に読み込めない場合はフォールバックフォントを使用し続ける。次回訪問時にキャッシュがあれば使用

最高速度優先、ネットワーク状況に応じた柔軟な対応

auto

ブラウザ依存

ブラウザ依存

ブラウザのデフォルト動作(多くの場合blockと同じ)

非推奨(明示的な指定が望ましい)

フォントファイルのサブセット化

使用する文字だけを含むフォントファイルを作成することで、ファイルサイズを大幅に削減します。

Google Fontsでは、URLパラメータで必要な文字だけを指定できます。

<!-- 日本語フォントで特定の文字のみ -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&text=こんにちは世界" rel="stylesheet">

WOFF2フォーマットの使用

WOFF2は、WOFF比で30%小さく、主要ブラウザでサポートされています。

@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2'),      /* モダンブラウザ */
       url('font.woff') format('woff');         /* フォールバック */
}

フォントの事前読み込み

重要なフォントにはpreload属性で事前読み込みを指定し、不要なウェイト(太さ)やスタイルの読み込みを避けます。

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

ただし、preloadは1〜2個の重要なフォントに限定します。

システムフォントの使用

最速の方法は、Webフォントを使用せず、デバイスにインストール済みのシステムフォントを使用することです。

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

ブラウザキャッシュの最適化

適切なキャッシュ戦略により、リピート訪問時の読み込み速度を大幅に改善します。

Cache-Controlヘッダーの設定

# Apache .htaccess
<IfModule mod_expires.c>
  ExpiresActive On
  
  # 画像
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType image/webp "access plus 1 year"
  
  # CSS/JavaScript
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType application/javascript "access plus 1 year"
  
  # HTML
  ExpiresByType text/html "access plus 1 hour"
</IfModule>

<IfModule mod_headers.c>
  # immutableディレクティブ(変更されないリソース用)
  <FilesMatch "\.(js|css|jpg|jpeg|png|gif|webp|woff2)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>
</IfModule>
# Nginx設定
location ~* \.(jpg|jpeg|png|gif|webp|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

location ~* \.(html)$ {
    expires 1h;
    add_header Cache-Control "public";
}

キャッシュバスティング戦略

ファイル名にバージョン番号やハッシュを含めることで、更新時に確実に新バージョンを配信します。

Copy<!-- バージョン番号 -->
<link rel="stylesheet" href="style.css?v=2.1.0">

<!-- ハッシュ値(推奨) -->
<link rel="stylesheet" href="style.a8b3c9d2.css">
<script src="app.f4e5d6c7.js"></script>

Webpack、Parcel、Viteなどのビルドツールは、自動的にハッシュ付きファイル名を生成します。

Service Workerの活用

Service Workerを使用すると、より高度なキャッシュ戦略を実装できます。

// service-worker.js
const CACHE_NAME = 'v1';
const ASSETS = [
  '/',
  '/style.css',
  '/app.js',
  '/logo.png'
];

// インストール時にリソースをキャッシュ
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.addAll(ASSETS);
    })
  );
});

// リクエスト時にキャッシュから返す
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});

サードパーティスクリプトの最適化

サードパーティスクリプトの最適化は、外部スクリプト(広告、アクセス解析、SNSウィジェット)の影響を最小限に抑える重要な施策です。

最も効果的なのはasyncまたはdefer属性による非同期読み込みで、レンダリングブロックを回避できます。

非同期読み込み

<!-- Google Analytics非同期読み込み -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>

<!-- FacebookピクセルをIdle時に読み込み -->
<script>
  if ('requestIdleCallback' in window) {
    requestIdleCallback(() => {
      loadFacebookPixel();
    });
  } else {
    setTimeout(loadFacebookPixel, 1000);
  }
</script>

さらに、requestIdleCallbackを使用してブラウザのアイドル時に読み込むことで、メインコンテンツの表示を優先できます。

Facade(ファサード)パターン

重いウィジェット(YouTube埋め込み、SNSボタン)の代わりに軽量なプレースホルダーを表示し、クリック時に実際のウィジェットを読み込みます。

初期ロードを大幅に高速化できます。

<!-- YouTube Lite Embed -->
<div class="youtube-placeholder" data-video-id="dQw4w9WgXcQ">
  <img src="thumbnail.jpg" alt="Video">
  <button>▶ 再生</button>
</div>

<script>
document.querySelectorAll('.youtube-placeholder').forEach(placeholder => {
  placeholder.addEventListener('click', function() {
    const videoId = this.dataset.videoId;
    const iframe = document.createElement('iframe');
    iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
    this.replaceWith(iframe);
  });
});
</script>

タグマネージャーの活用

Google Tag Managerで複数のスクリプトを一元管理し、読み込みタイミングを制御することも有効です。

不要なスクリプトは削除し、本当に必要なものだけに絞ることが最も重要です。

レンダリング遅延改善のよくある質問(FAQ)

Q1. 画像を最適化したのにレンダリング遅延が改善しません

A: 画像最適化は「読み込み時間」を短縮しますが、レンダリング遅延は画像ダウンロード後の描画処理の遅れを指します。

主な原因はJavaScript/CSSの実行待ちです。

改善策

  • JavaScriptにdefer属性を追加
  • クリティカルCSSをインライン化
  • Webフォントにfont-display: swapを設定

Q2. deferとasyncの使い分けがわかりません

A: 実行順序が重要かどうかで判断します。

defer: HTMLの解析後に記述順に実行

  • 用途:jQueryなど依存関係があるライブラリ
  • 例:<script src="jquery.js" defer></script>

async: ダウンロード完了次第すぐ実行(順序不定)

  • 用途:Google Analyticsなど独立したスクリプト
  • 例:<script src="analytics.js" async></script>

迷ったらdeferを使用すれば安全です。

Q3. すべてのJavaScriptを非同期化すべきですか?

A: いいえ。初期表示に必須のスクリプトは非同期化すると機能が壊れます。

非同期化OK

  • 分析ツール(GA4、GTM)
  • チャットウィジェット
  • SNS埋め込み

非同期化NG

  • 初期化コード
  • インラインスクリプトに依存するライブラリ

必ずステージング環境でテストしてから本番適用しましょう。

Q4. WordPressでコードを触らず改善できますか?

A: プラグインで80%は対応可能です。

推奨プラグイン

  • WP Rocket:総合最適化(有料)
  • Flying Scripts:JS遅延実行(無料)
  • Autoptimize:CSS/JS最適化(無料)

ただし完全な最適化にはテーマファイルの調整が必要な場合もあります。

Q5. モバイルだけスコアが悪いのですが

A: モバイルは通信速度が遅いため、レンダリング遅延の影響が顕著に現れます。

モバイル特化の対策

  • JavaScriptのファイルサイズをさらに削減
  • 画像の遅延読み込み(lazy loading)
  • AMPページの導入検討
  • モバイル専用の軽量CSSを用意

PageSpeed InsightsはモバイルをLow-end端末(低スペック)で測定するため、厳しい結果になりがちです。

モバイルスコア2.5秒以内を目標にしましょう。

Q6. レンダリング遅延の改善効果はどれくらいで現れますか?

A: 実装内容により異なりますが、一般的な目安

  • JavaScript非同期化:即日〜3日で効果確認可能
  • CSS最適化:1週間程度でスコア反映
  • フォント最適化:即日効果を確認可能

Google Search Consoleのデータは28日間の平均値のため、完全な効果確認には1ヶ月程度かかります。

PageSpeed Insightsでは即座に確認できます。

レンダリング遅延改善のまとめ

レンダリング遅延は、LCPを構成する最後の重要な指標です。

画像やコンテンツがダウンロードされても、JavaScript・CSS・Webフォントの影響で描画が遅れると、ユーザーは「まだ表示されない」とストレスを感じてしまいます。

本記事で解説した改善方法を実践すれば、レンダリング遅延を大幅に短縮できます。

まずはPageSpeed Insightsで現状を測定し、チェックリストに沿って優先順位を決めましょう。

一度にすべて実装する必要はありません。

効果の高い施策から段階的に取り組むことで、着実にスコアは改善していきます。

記事を書いた人

井上寛生

井上寛生

LandingHub 執行役員 / 事業責任者 / 技術責任者

大学院では情報工学を専攻し、修了後に株式会社TeNへ新卒入社。当時は社内唯一のエンジニアながら、開発部門をゼロから立ち上げ、採用・育成を一手に担い、全員が未経験からスタートした精鋭エンジニアチームを組成。2021 年にはWEBサイト高速化プラットフォーム「LandingHub」を立ち上げ、プロダクトオーナー兼事業責任者として企画・開発・グロースを牽引。現在は執行役員として、会社の技術戦略と事業成長の双方をリードしている。
コラム一覧に戻る