メインコンテンツへスキップ
ブログ一覧に戻る
web

Webパフォーマンス測定とモニタリング完全ガイド:継続的な改善のための実践手法

2025年11月15日
11分で読めます
Webパフォーマンス測定とモニタリング完全ガイド:継続的な改善のための実践手法

Webパフォーマンス測定とモニタリング完全ガイド:継続的な改善のための実践手法

「パフォーマンスを改善したいが、どこから始めればいいかわからない」「測定はしているが、どう活用すればいいかわからない」「継続的な改善ができていない」と感じたことはありませんか?

パフォーマンス測定とモニタリングは、Webサイトのパフォーマンスを継続的に改善するための基盤です。適切な測定とモニタリングにより、ボトルネックを特定し、効果的な改善を実施できます。

この記事では、パフォーマンス測定とモニタリングの基礎から実践まで、測定ツールの選び方、モニタリングの設定方法、データ分析と改善への活用法を、具体的なコード例とベストプラクティスを交えて網羅的に解説します。

この記事を読む前に

この記事では、Webサイト制作とパフォーマンスの基礎知識があることを前提としています。以下の記事を事前に読んでおくと、より深く理解できます:

この記事でわかること

  • パフォーマンス測定とモニタリングとは何か、なぜ重要なのか
  • 測定ツールの種類と選び方
  • ラボ環境での測定方法
  • リアルユーザーモニタリング(RUM)の実装方法
  • モニタリングの設定とアラート
  • データ分析と改善への活用法
  • 継続的な改善のプロセス

1. パフォーマンス測定とモニタリングとは何か?

1.1 基本的な定義

パフォーマンス測定とは、Webサイトのパフォーマンス指標を測定し、現状を把握するプロセスです。

パフォーマンスモニタリングとは、パフォーマンス指標を継続的に監視し、問題を早期に発見するプロセスです。

測定とモニタリングが重要な理由

測定とモニタリングにより、パフォーマンスの現状を正確に把握できます。例えば、LCPが3秒であることを測定することで、改善の必要性を判断できます。問題の原因を特定できます。例えば、特定のJavaScriptファイルが読み込みを遅延させていることを発見できます。改善の効果を定量的に確認できます。例えば、画像最適化により、LCPが3秒から1.5秒に改善したことを確認できます。パフォーマンスの劣化を早期に発見できます。例えば、モニタリングにより、新機能の追加によりパフォーマンスが劣化したことを即座に発見できます。

1.2 測定の種類

ラボ環境での測定(Synthetic Monitoring)

  • 特徴:制御された環境で測定
  • メリット:再現性が高い、詳細な分析が可能
  • デメリット:実際のユーザー環境と異なる可能性

リアルユーザーモニタリング(RUM)

  • 特徴:実際のユーザーの環境で測定
  • メリット:実際のユーザー体験を反映
  • デメリット:環境が多様で、詳細な分析が難しい場合がある

両方が必要な理由

ラボ環境での測定は、再現性が高く、詳細な分析が可能です。例えば、Google Lighthouseにより、制御された環境で一貫した測定が可能です。一方、RUMは、実際のユーザー体験を反映します。例えば、実際のユーザーのネットワーク環境やデバイスでのパフォーマンスを測定できます。両方を組み合わせることで、より正確なパフォーマンス評価が可能になります。例えば、ラボ環境で問題を発見し、RUMで実際の影響を確認することで、優先順位を適切に設定できます。

2. ラボ環境での測定

2.1 Google Lighthouse

Lighthouseとは?

Lighthouseは、Googleが開発した、Webページの品質を測定するオープンソースツールです。

測定方法

Chrome DevTools

  1. Chrome DevToolsを開く(F12)
  2. 「Lighthouse」タブを選択
  3. 「Performance」を選択
  4. 「Analyze page load」をクリック
  5. 結果を確認

コマンドライン

# Lighthouseをインストール
npm install -g lighthouse

# パフォーマンスを測定
lighthouse https://example.com --only-categories=performance --view

# 結果をJSONで出力
lighthouse https://example.com --only-categories=performance --output=json --output-path=./report.json

Node.js API

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});

Lighthouseは、パフォーマンスだけでなく、アクセシビリティ、SEO、ベストプラクティスも測定できます。また、具体的な改善提案も提供されるため、すぐに実践できる最適化方法を学べます。Lighthouseは、Chrome DevToolsに統合されているため、簡単に使用できます。また、具体的な改善提案も提供されるため、すぐに実践できる最適化方法を学べます。例えば、「画像を最適化する」「JavaScriptを遅延読み込みする」などの具体的な改善提案が提供されます。

2.2 WebPageTest

WebPageTestとは?

WebPageTestは、世界中の複数の場所から、詳細なパフォーマンス分析を提供するツールです。

測定方法

  1. WebPageTestにアクセス(https://www.webpagetest.org/)
  2. テストするURLを入力
  3. テスト場所を選択
  4. ブラウザを選択
  5. 「Start Test」をクリック
  6. 結果を確認

APIを使用した測定

const axios = require('axios');

async function runWebPageTest(url, location = 'Tokyo') {
  // テストを開始
  const testResponse = await axios.get('https://www.webpagetest.org/runtest.php', {
    params: {
      url: url,
      location: location,
      f: 'json',
      k: 'YOUR_API_KEY', // APIキーが必要
    },
  });
  
  const testId = testResponse.data.data.testId;
  
  // 結果を取得(ポーリング)
  let result;
  do {
    await new Promise(resolve => setTimeout(resolve, 5000));
    const resultResponse = await axios.get('https://www.webpagetest.org/jsonResult.php', {
      params: { test: testId },
    });
    result = resultResponse.data;
  } while (result.statusCode === 100);
  
  return {
    loadTime: result.data.average.firstView.loadTime,
    ttfb: result.data.average.firstView.TTFB,
    lcp: result.data.average.firstView.LCP,
  };
}

WebPageTestは、世界中の複数の場所から測定できるため、地域によるパフォーマンスの違いを確認できます。また、詳細な分析機能(ウォーターフォールチャート、動画キャプチャなど)により、ボトルネックを特定できます。例えば、東京、ニューヨーク、ロンドンなど、複数の場所から測定することで、地域によるパフォーマンスの違いを確認できます。また、ウォーターフォールチャートや動画キャプチャなどの詳細な分析機能により、ボトルネックを特定できます。

2.3 Google PageSpeed Insights

PageSpeed Insightsとは?

PageSpeed Insightsは、LighthouseとChrome User Experience Reportを組み合わせて、実際のユーザーデータを含む包括的な分析を提供するツールです。

測定方法

  1. PageSpeed Insightsにアクセス(https://pagespeed.web.dev/)
  2. テストするURLを入力
  3. 「分析」をクリック
  4. 結果を確認

APIを使用した測定

const axios = require('axios');

async function runPageSpeedInsights(url) {
  const response = await axios.get('https://www.googleapis.com/pagespeedonline/v5/runPagespeed', {
    params: {
      url: url,
      key: 'YOUR_API_KEY', // APIキーが必要
      category: ['performance'],
    },
  });
  
  const lighthouseResult = response.data.lighthouseResult;
  
  return {
    score: lighthouseResult.categories.performance.score  100,
    metrics: {
      lcp: lighthouseResult.audits['largest-contentful-paint'].numericValue,
      fid: lighthouseResult.audits['max-potential-fid'].numericValue,
      cls: lighthouseResult.audits['cumulative-layout-shift'].numericValue,
    },
  };
}

PageSpeed Insightsは、実際のユーザーデータ(Chrome User Experience Report)を含むため、ラボ環境での測定よりも、実際のユーザー体験を反映します。また、具体的な改善提案も提供されます。PageSpeed Insightsは、実際のユーザーデータを含むため、ラボ環境での測定よりも、実際のユーザー体験を反映します。例えば、実際のユーザーのデバイスやネットワーク環境でのパフォーマンスを測定できるため、より正確な評価が可能になります。また、具体的な改善提案も提供されるため、すぐに実践できる最適化方法を学べます。

3. リアルユーザーモニタリング(RUM)

3.1 Web Vitalsライブラリ

Web Vitalsライブラリとは?

Web Vitalsライブラリは、Core Web Vitals(LCP、FID、CLS)を測定するためのJavaScriptライブラリです。

実装方法

import { getLCP, getFID, getCLS } from 'web-vitals';

function sendToAnalytics(metric) {
  // 分析ツールに送信
  const body = JSON.stringify(metric);
  
  // Google Analytics 4
  if (typeof gtag !== 'undefined') {
    gtag('event', metric.name, {
      event_category: 'Web Vitals',
      value: Math.round(metric.value),
      event_label: metric.id,
      non_interaction: true,
    });
  }
  
  // カスタムエンドポイント
  if ('sendBeacon' in navigator) {
    navigator.sendBeacon('/api/analytics', body);
  } else {
    fetch('/api/analytics', { body, method: 'POST', keepalive: true });
  }
}

getLCP(sendToAnalytics);
getFID(sendToAnalytics);
getCLS(sendToAnalytics);

Next.jsでの実装

// pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { getCLS, getFID, getLCP } from 'web-vitals';

export function reportWebVitals(metric) {
  // 分析ツールに送信
  console.log(metric);
  
  // Google Analytics 4
  if (typeof gtag !== 'undefined') {
    gtag('event', metric.name, {
      event_category: 'Web Vitals',
      value: Math.round(metric.value),
      event_label: metric.id,
      non_interaction: true,
    });
  }
}

export default function App({ Component, pageProps }) {
  const router = useRouter();
  
  useEffect(() => {
    // Web Vitalsを測定
    getCLS(reportWebVitals);
    getFID(reportWebVitals);
    getLCP(reportWebVitals);
  }, []);
  
  return <Component {...pageProps} />;
}

Web Vitalsライブラリは、実際のユーザーの環境でCore Web Vitalsを測定できます。これにより、実際のユーザー体験を正確に把握し、改善の効果を検証できます。例えば、実際のユーザーのデバイスやネットワーク環境でのCore Web Vitalsを測定できるため、ラボ環境での測定よりも、実際のユーザー体験を反映します。

3.2 Performance API

Performance APIとは?

Performance APIは、ブラウザが提供する、パフォーマンス情報を取得するためのAPIです。

実装方法

// Navigation Timing
const navigationTiming = performance.getEntriesByType('navigation')[0];
console.log('TTFB:', navigationTiming.responseStart - navigationTiming.requestStart);
console.log('DOM Content Loaded:', navigationTiming.domContentLoadedEventEnd - navigationTiming.navigationStart);
console.log('Load Complete:', navigationTiming.loadEventEnd - navigationTiming.navigationStart);

// Resource Timing
const resourceTiming = performance.getEntriesByType('resource');
resourceTiming.forEach(resource => {
  console.log(`${resource.name}:`, {
    duration: resource.duration,
    size: resource.transferSize,
    ttfb: resource.responseStart - resource.requestStart,
  });
});

// Paint Timing
const paintTiming = performance.getEntriesByType('paint');
paintTiming.forEach(paint => {
  console.log(`${paint.name}:`, paint.startTime);
});

Performance APIは、ブラウザが提供する標準的なAPIのため、追加のライブラリが不要です。また、詳細なパフォーマンス情報を取得できるため、カスタムな分析が可能です。例えば、performance.timingを使用することで、ページの読み込み時間を詳細に測定できます。また、performance.getEntriesByType('resource')を使用することで、リソースの読み込み時間を測定できます。

3.3 カスタムメトリクスの測定

実装例

// カスタムメトリクスの測定
function measureCustomMetric(name, startMark, endMark) {
  const startTime = performance.getEntriesByName(startMark)[0].startTime;
  const endTime = performance.getEntriesByName(endMark)[0].startTime;
  const duration = endTime - startTime;
  
  // メトリクスを記録
  performance.mark(`${name}-end`);
  performance.measure(name, startMark, `${name}-end`);
  
  const measure = performance.getEntriesByName(name)[0];
  console.log(`${name}:`, measure.duration, 'ms');
  
  // 分析ツールに送信
  sendToAnalytics({
    name: name,
    value: measure.duration,
    id: `${name}-${Date.now()}`,
  });
}

// 使用例
performance.mark('data-fetch-start');
fetch('/api/data')
  .then(res => res.json())
  .then(data => {
    performance.mark('data-fetch-end');
    measureCustomMetric('data-fetch-time', 'data-fetch-start', 'data-fetch-end');
  });

4. モニタリングの設定

4.1 ダッシュボードの構築

実装例(Next.js + Chart.js)

// components/PerformanceDashboard.js
import { useEffect, useState } from 'react';
import { Line } from 'react-chartjs-2';

export default function PerformanceDashboard() {
  const [metrics, setMetrics] = useState([]);
  
  useEffect(() => {
    // メトリクスを取得
    fetch('/api/metrics')
      .then(res => res.json())
      .then(data => setMetrics(data));
    
    // 定期的に更新
    const interval = setInterval(() => {
      fetch('/api/metrics')
        .then(res => res.json())
        .then(data => setMetrics(data));
    }, 60000); // 1分ごとに更新
    
    return () => clearInterval(interval);
  }, []);
  
  const chartData = {
    labels: metrics.map(m => new Date(m.timestamp).toLocaleTimeString()),
    datasets: [
      {
        label: 'LCP',
        data: metrics.map(m => m.lcp),
        borderColor: 'rgb(75, 192, 192)',
      },
      {
        label: 'FID',
        data: metrics.map(m => m.fid),
        borderColor: 'rgb(255, 99, 132)',
      },
      {
        label: 'CLS',
        data: metrics.map(m => m.cls),
        borderColor: 'rgb(54, 162, 235)',
      },
    ],
  };
  
  return (
    <div>
      <h2>Performance Dashboard</h2>
      <Line data={chartData} />
    </div>
  );
}

4.2 アラートの設定

実装例

// utils/performance-alerts.js
export function checkPerformanceMetrics(metrics) {
  const alerts = [];
  
  // LCPのアラート
  if (metrics.lcp > 4000) {
    alerts.push({
      level: 'error',
      metric: 'LCP',
      message: `LCP is ${metrics.lcp}ms, which is above the threshold of 4000ms`,
    });
  } else if (metrics.lcp > 2500) {
    alerts.push({
      level: 'warning',
      metric: 'LCP',
      message: `LCP is ${metrics.lcp}ms, which is above the recommended threshold of 2500ms`,
    });
  }
  
  // FIDのアラート
  if (metrics.fid > 300) {
    alerts.push({
      level: 'error',
      metric: 'FID',
      message: `FID is ${metrics.fid}ms, which is above the threshold of 300ms`,
    });
  } else if (metrics.fid > 100) {
    alerts.push({
      level: 'warning',
      metric: 'FID',
      message: `FID is ${metrics.fid}ms, which is above the recommended threshold of 100ms`,
    });
  }
  
  // CLSのアラート
  if (metrics.cls > 0.25) {
    alerts.push({
      level: 'error',
      metric: 'CLS',
      message: `CLS is ${metrics.cls}, which is above the threshold of 0.25`,
    });
  } else if (metrics.cls > 0.1) {
    alerts.push({
      level: 'warning',
      metric: 'CLS',
      message: `CLS is ${metrics.cls}, which is above the recommended threshold of 0.1`,
    });
  }
  
  return alerts;
}

// アラートを送信
function sendAlert(alert) {
  // メール、Slack、PagerDutyなどに送信
  console.log('Alert:', alert);
  
  // 例:Slackに送信
  fetch('https://hooks.slack.com/services/YOUR/WEBHOOK/URL', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      text: `Performance Alert: ${alert.message}`,
      attachments: [{
        color: alert.level === 'error' ? 'danger' : 'warning',
        fields: [{
          title: 'Metric',
          value: alert.metric,
          short: true,
        }],
      }],
    }),
  });
}

5. データ分析と改善への活用

5.1 データの集計と分析

実装例

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
0___

5.2 改善の優先順位付け

実装例

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
1___

6. 継続的な改善のプロセス

6.1 PDCAサイクル

Plan(計画)

  • 現状を把握(測定)
  • 目標を設定(例:LCPを2.5秒以下に)
  • 改善計画を立案

Do(実行)

  • 改善を実施
  • 変更を記録

Check(評価)

  • 効果を測定
  • データを分析

Action(改善)

  • 成功した改善を標準化
  • 失敗した改善から学ぶ
  • 次の改善計画を立案

6.2 実践例

ステップ1:現状の把握

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
2___

ステップ2:目標の設定

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
3___

ステップ3:改善の実施

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
4___

ステップ4:効果の検証

___

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', onlyCategories: ['performance'], port: chrome.port };
  const runnerResult = await lighthouse(url, options);
  
  await chrome.kill();
  
  return {
    score: runnerResult.lhr.categories.performance.score  100,
    metrics: runnerResult.lhr.audits,
  };
}

runLighthouse('https://example.com').then(result => {
  console.log('Performance Score:', result.score);
});
5___

パフォーマンス測定・モニタリングの要点とPDCA

  • パフォーマンス測定とモニタリングは、継続的な改善の基盤
  • ラボ環境での測定リアルユーザーモニタリング(RUM)を組み合わせる
  • 適切なツールを選択し、継続的にモニタリング
  • データを分析し、改善の優先順位を決定
  • PDCAサイクルで継続的に改善

次に読むおすすめの記事

Webパフォーマンス測定とモニタリングについて理解を深めたら、以下の記事も参考にしてください:

より深く学ぶ

実践的な活用

関連する基礎知識

次のステップ

  1. 測定ツールを選択(Lighthouse、WebPageTest、PageSpeed Insights)
  2. RUMを実装(Web Vitalsライブラリ、Performance API)
  3. モニタリングを設定(ダッシュボード、アラート)
  4. データを分析(集計、トレンド分析)
  5. 改善を実施(優先順位に従って)

参考資料・引用元


ご相談・お問い合わせはこちら

次の一手

状況に合わせて、選んでください。