WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

【完全版】Lighthouseスコア100達成の具体的手法!パフォーマンス最適化から実装まで詳しく解説

生徒

WebサイトのLighthouseスコアを100点にしたいんですが、どうすれば良いでしょうか?

ペン博士

よーく聞くんだぞ!Lighthouseスコア100点は簡単ではないが、正しい手法を実践すれば達成できるんじゃ。今日はパフォーマンス最適化の具体的な方法を詳しく解説するぞい!

この記事でわかること

  • Lighthouseの5つの評価カテゴリーとCore Web Vitals(LCP・INP・CLS)の目標値
  • 画像・JavaScript・CSS・フォントの具体的な最適化手法とコード例
  • Core Web Vitals(LCP・FID/INP・CLS)を改善する実装方法
  • サーバー・ネットワーク最適化(HTTP/2・Gzip/Brotli・CDN・キャッシュ設定)
  • SEO・アクセシビリティスコア100達成のためのHTML実装とLighthouse CIによる継続監視

Webサイトのパフォーマンスは、ユーザー体験とSEOの両方に直接影響を与える重要な要素です。Googleが提供するLighthouseは、サイトの品質を測定する標準的なツールとして広く使われていますが、スコア100点を達成し維持することは決して簡単ではありません。

本記事では、Lighthouseスコア100点を達成するための具体的な手法を、基礎から実装まで、実践的な例を交えて徹底解説します。


目次

Lighthouseとは?基本概念と評価カテゴリー

Lighthouse(ライトハウス)は、Googleが開発したWebサイトの品質を測定するオープンソースのツールです。Chrome DevToolsに統合されており、誰でも無料で利用できます。

Lighthouseの5つの評価カテゴリー

カテゴリー評価内容重要性
Performance(パフォーマンス)読み込み速度、レスポンス性★★★★★
Accessibility(アクセシビリティ)誰でも使えるか、読みやすさ★★★★★
Best Practices(ベストプラクティス)セキュリティ、モダンな技術★★★★☆
SEO検索エンジン最適化★★★★★
PWA(Progressive Web App)アプリライクな体験★★★☆☆

Core Web Vitals(コアウェブバイタル)

Lighthouseのパフォーマンススコアには、Googleが定めたCore Web Vitalsが大きく影響します。

  • LCP(Largest Contentful Paint):最大コンテンツの描画時間。ページの主要コンテンツが表示されるまでの時間。目標:2.5秒以内
  • FID(First Input Delay)/ INP(Interaction to Next Paint):初回入力遅延とユーザー操作への応答速度。目標:100ミリ秒以内(FID)/ 200ミリ秒以内(INP)
  • CLS(Cumulative Layout Shift):累積レイアウトシフト。視覚的な安定性。目標:0.1以下

Lighthouseスコアの測定方法

1. Chrome DevToolsで測定

  1. Chrome で測定したいページを開く
  2. F12キーでDevToolsを開く
  3. 「Lighthouse」タブを選択
  4. 測定カテゴリーとデバイス(Mobile/Desktop)を選択
  5. 「Analyze page load」をクリック

2. PageSpeed Insightsで測定

オンラインツール:https://pagespeed.web.dev/

3. Lighthouse CI(継続的測定)

# Lighthouse CIのインストール
npm install -g @lhci/cli

# 測定の実行
lhci autorun --collect.url=https://example.com

スコア100達成のための改善優先順位

生徒

どこから手を付ければ良いですか?

ペン博士

まずは現状を測定し、スコアが低いカテゴリーから優先的に改善していくんじゃ。特にパフォーマンスは最も難しく、最も重要じゃぞ

  1. Performance(パフォーマンス) – 最も難しいが最も重要
  2. SEO – 比較的改善しやすい
  3. Accessibility(アクセシビリティ) – HTML構造で対応可能
  4. Best Practices(ベストプラクティス) – 技術的な設定
  5. PWA – 必要に応じて対応

パフォーマンス最適化の具体的手法

1. 画像最適化

画像は最もファイルサイズが大きく、最適化の効果が高い要素です。

次世代フォーマット(WebP/AVIF)への変換

WebPはJPEG/PNGより25〜35%小さく、AVIFはさらに高圧縮率を実現します。

<!-- pictureタグで複数フォーマットを提供 -->
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="説明文" loading="lazy" decoding="async">
</picture>

レスポンシブ画像の実装

<img
  src="image-800.jpg"
  srcset="
    image-400.jpg 400w,
    image-800.jpg 800w,
    image-1200.jpg 1200w,
    image-1600.jpg 1600w
  "
  sizes="
    (max-width: 600px) 400px,
    (max-width: 1200px) 800px,
    1200px
  "
  alt="説明文"
  loading="lazy"
  decoding="async"
  width="800"
  height="600"
/>

遅延読み込み(Lazy Loading)

<!-- ネイティブLazy Loading -->
<img src="image.jpg" alt="説明文" loading="lazy" decoding="async">

<!-- iframeにも適用可能 -->
<iframe src="https://example.com" loading="lazy"></iframe>

画像サイズの指定(CLS対策)

<!-- widthとheightを必ず指定 -->
<img
  src="image.jpg"
  alt="説明文"
  width="800"
  height="600"
  loading="lazy"
/>

<!-- CSSでアスペクト比を維持 -->
<style>
  img {
    max-width: 100%;
    height: auto;
  }
</style>

2. JavaScript最適化

未使用JavaScriptの削除

// ❌ 悪い例:全てをインポート
import _ from 'lodash';

// ✅ 良い例:必要な関数のみインポート
import debounce from 'lodash/debounce';

// または、Tree Shakingが有効な書き方
import { debounce } from 'lodash-es';

コード分割(Code Splitting)

// Next.jsでの動的インポート
import dynamic from 'next/dynamic';

// コンポーネントを動的に読み込む
const DynamicComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <p>読み込み中...</p>,
  ssr: false // クライアント側でのみ読み込む
});

// React標準の動的インポート
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

スクリプトの最適な読み込み

<!-- defer: DOMが完全にパースされた後に実行 -->
<script src="script.js" defer></script>

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

<!-- type="module": ES Modulesとして読み込み(自動でdefer) -->
<script type="module" src="app.js"></script>

重要なJavaScriptのインライン化

<!-- クリティカルなスクリプトはインライン化 -->
<script>
  // ダークモード切り替えなど、即座に実行したいコード
  (function() {
    const theme = localStorage.getItem('theme');
    if (theme === 'dark') {
      document.documentElement.classList.add('dark');
    }
  })();
</script>

3. CSS最適化

未使用CSSの削除

// PurgeCSSの設定(Tailwind CSS使用時)
// tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  // 使用されているクラスのみビルドに含まれる
}

クリティカルCSSのインライン化

<!-- ファーストビューに必要なCSSをインライン化 -->
<style>
  /* クリティカルCSS(Above the Fold) */
  body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  }

  .header {
    background: #fff;
    padding: 1rem;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  }
</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>

CSS Minification(圧縮)

// Next.jsは自動で圧縮されるが、手動の場合:
// package.json
{
  "scripts": {
    "build:css": "postcss src/styles.css -o dist/styles.min.css"
  },
  "devDependencies": {
    "postcss": "^8.4.0",
    "postcss-cli": "^10.0.0",
    "cssnano": "^6.0.0"
  }
}

4. フォント最適化

フォントの最適な読み込み

<!-- Google Fontsの最適な読み込み -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
  href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap"
  rel="stylesheet"
>

<style>
  /* フォント読み込み中のフォールバック */
  body {
    font-family: 'Noto Sans JP', -apple-system, BlinkMacSystemFont, sans-serif;
  }
</style>

Next.js Font Optimizationの活用

// app/layout.tsx
import { Noto_Sans_JP } from 'next/font/google';

const notoSansJP = Noto_Sans_JP({
  weight: ['400', '700'],
  subsets: ['latin'],
  display: 'swap',
  preload: true,
});

export default function RootLayout({ children }) {
  return (
    <html lang="ja" className={notoSansJP.className}>
      <body>{children}</body>
    </html>
  );
}

5. サーバー・ネットワーク最適化

HTTP/2の有効化

HTTP/2は複数のリクエストを並列処理でき、パフォーマンスが大幅に向上します。

# Nginxの設定例
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # その他の設定...
}

Gzip/Brotli圧縮

# Nginxの設定例
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types
  text/plain
  text/css
  text/xml
  text/javascript
  application/javascript
  application/json
  application/xml+rss
  image/svg+xml;

# Brotli圧縮(より高圧縮率)
brotli on;
brotli_types
  text/plain
  text/css
  text/xml
  text/javascript
  application/javascript
  application/json;

キャッシュの設定

# Nginxのキャッシュ設定
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# HTMLは短めのキャッシュ
location ~* \.html$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

CDNの活用

静的ファイルをCDNから配信することで、世界中どこからでも高速にアクセスできます。

  • Cloudflare:無料プランあり、簡単に導入可能
  • AWS CloudFront:AWSとの統合が容易
  • Vercel/Netlify:Next.js等のデプロイ時に自動でCDN配信

Core Web Vitals最適化

LCP(Largest Contentful Paint)の改善

LCPは最大コンテンツの描画時間で、2.5秒以内が目標です。

  1. LCP要素の特定
// LCP要素を特定するスクリプト
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];
  console.log('LCP element:', lastEntry.element);
  console.log('LCP time:', lastEntry.startTime);
}).observe({ entryTypes: ['largest-contentful-paint'] });
  1. 重要なリソースのプリロード
<!-- ヒーロー画像をプリロード -->
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">

<!-- 重要なフォントをプリロード -->
<link rel="preload" as="font" href="font.woff2" type="font/woff2" crossorigin>
  1. サーバー応答時間の短縮(TTFB):CDNを使用・サーバーサイドキャッシュを実装・データベースクエリを最適化

FID/INP(First Input Delay / Interaction to Next Paint)の改善

  1. メインスレッドのブロッキングを削減
// ❌ 悪い例:重い処理をメインスレッドで実行
function heavyCalculation() {
  for (let i = 0; i < 1000000; i++) {
    // 重い処理
  }
}

// ✅ 良い例:Web Workerで実行
// worker.js
self.addEventListener('message', (e) => {
  const result = heavyCalculation(e.data);
  self.postMessage(result);
});

// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.addEventListener('message', (e) => {
  console.log('Result:', e.data);
});
  1. 長いタスクの分割
// タスクを細かく分割してブラウザに制御を返す
async function processLargeArray(array) {
  const chunkSize = 100;

  for (let i = 0; i < array.length; i += chunkSize) {
    const chunk = array.slice(i, i + chunkSize);

    // チャンクを処理
    await processChunk(chunk);

    // ブラウザに制御を返す
    await new Promise(resolve => setTimeout(resolve, 0));
  }
}

CLS(Cumulative Layout Shift)の改善

CLSは視覚的な安定性を測る指標で、0.1以下が目標です

  1. 画像・動画のサイズ指定
<!-- 必ずwidth/heightを指定 -->
<img src="image.jpg" width="800" height="600" alt="説明">

<!-- aspect-ratioを使用 -->
<style>
  .image-container {
    aspect-ratio: 16 / 9;
  }
</style>
  1. 広告・iframe用のスペース確保
<!-- 広告用のプレースホルダー -->
<div style="min-height: 250px;">
  <!-- 広告スクリプト -->
</div>
  1. フォント読み込みの最適化
@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2');
  /* フォールバックフォントとのサイズ差を調整 */
  font-display: swap;
  size-adjust: 100%;
}

SEO・アクセシビリティ・ベストプラクティス

SEOスコア100達成

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <!-- タイトル(60文字以内) -->
  <title>ページタイトル | サイト名</title>

  <!-- メタディスクリプション(160文字以内) -->
  <meta name="description" content="ページの説明文">

  <!-- OGP -->
  <meta property="og:title" content="ページタイトル">
  <meta property="og:description" content="ページの説明文">
  <meta property="og:image" content="https://example.com/ogp.jpg">
  <meta property="og:url" content="https://example.com/page">

  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image">

  <!-- Canonical URL -->
  <link rel="canonical" href="https://example.com/page">

  <!-- robots -->
  <meta name="robots" content="index, follow">
</head>

構造化データ(JSON-LD)

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "記事のタイトル",
  "author": {
    "@type": "Person",
    "name": "著者名"
  },
  "datePublished": "2026-02-25",
  "image": "https://example.com/article-image.jpg"
}
</script>

アクセシビリティスコア100達成

セマンティックHTML

<!-- ✅ 良い例:セマンティックな構造 -->
<header>
  <nav aria-label="メインナビゲーション">
    <ul>
      <li><a href="/">ホーム</a></li>
      <li><a href="/about">概要</a></li>
    </ul>
  </nav>
</header>

<main>
  <article>
    <h1>記事タイトル</h1>
    <p>本文...</p>
  </article>
</main>

<footer>
  <p>© 2026 サイト名</p>
</footer>

ARIA属性の適切な使用

<!-- ボタン -->
<button aria-label="メニューを開く">
  <svg>...</svg>
</button>

<!-- フォーム -->
<form>
  <label for="email">メールアドレス</label>
  <input
    type="email"
    id="email"
    name="email"
    aria-required="true"
    aria-describedby="email-help"
  >
  <span id="email-help">example@domain.comの形式で入力してください</span>
</form>

<!-- リンク -->
<a href="/article" aria-label="記事タイトル - 続きを読む">
  続きを読む
</a>

色のコントラスト比

WCAG AA基準:通常テキストは4.5:1以上、大きいテキスト(18pt以上)は3:1以上のコントラスト比が必要です。


継続的な監視と改善|Lighthouse CIの導入

Lighthouseスコア100点は達成して終わりではありません。コードの変更やサードパーティスクリプトの追加でスコアは変動するため、継続的な監視が重要です。

# GitHub Actionsの設定例
# .github/workflows/lighthouse.yml
name: Lighthouse CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Run Lighthouse CI
        run: |
          npm install -g @lhci/cli
          lhci autorun

# lighthouserc.json
{
  "ci": {
    "collect": {
      "staticDistDir": "./dist",
      "url": [
        "http://localhost/index.html",
        "http://localhost/about.html"
      ]
    },
    "assert": {
      "preset": "lighthouse:recommended",
      "assertions": {
        "categories:performance": ["error", {"minScore": 0.9}],
        "categories:accessibility": ["error", {"minScore": 0.9}],
        "categories:best-practices": ["error", {"minScore": 0.9}],
        "categories:seo": ["error", {"minScore": 0.9}]
      }
    }
  }
}

生徒

Lighthouseスコア100点、達成できそうな気がしてきました!

ペン博士

その意気じゃ!ただし、スコア100点は「今日達成しても明日が同じとは限らない」ことを忘れずに。継続的な監視と改善が何より大切なんじゃぞ!

生徒

わかりました!まずは画像最適化から始めてみます!


よくある質問

Q1. Lighthouseスコア100点を目指すうえで、最初にやるべきことは何ですか?

A. まず現状のスコアをChrome DevToolsまたはPageSpeed Insightsで測定し、最も低いカテゴリーを特定することから始めてください。パフォーマンスが低い場合は画像最適化(WebP変換・遅延読み込み・サイズ指定)が最もコストパフォーマンスが高い改善策です。

Q2. モバイルとデスクトップでスコアが大きく違うのはなぜですか?

A. LighthouseのモバイルスコアはCPUを4倍・通信速度を遅くシミュレートして計測するため、デスクトップより厳しい条件になります。モバイルスコアが低い場合は、JavaScriptのコード分割・未使用コード削除・Critical CSS の適用が効果的です。

Q3. サードパーティスクリプト(GoogleタグマネージャーやチャットツールなどのJS)がスコアを下げてしまいます。どう対処すればいいですか?

A. サードパーティスクリプトはasyncまたはdefer属性を付けて読み込み遅延させるのが基本です。さらに必要ないページでは読み込まないよう条件分岐を追加してください。どうしても影響を避けられない場合は、Lighthouse CIの閾値をそのスクリプトの影響を考慮した現実的な値に設定することを検討してください。

Q4. CLSが0を達成できません。原因の調べ方を教えてください。

A. Chrome DevToolsの「Performance」タブで録画し、「Layout Shift」イベントを探してください。よくある原因は画像・広告のサイズ未指定、フォントのFOUT(フォールバックフォントと読み込み後フォントのサイズ差)、動的に挿入されるコンテンツです。aspect-ratioプロパティとfont-display: swap+size-adjustの組み合わせが効果的です。

Q5. Lighthouse CIをGitHub Actionsで設定する利点は何ですか?

A. PRごとにスコアを自動計測し、閾値を下回った変更をマージ前にブロックできます。「スコアを上げた後に別の変更で下がっていた」という状況を防ぎ、スコアの継続的な維持が可能になります。assertionsでカテゴリーごとに最低スコアを設定できるため、チームで品質基準を統一できます。


まとめ

  • 画像最適化:WebP/AVIF変換・レスポンシブ画像・遅延読み込み・width/height指定の4セットが基本
  • JavaScript最適化:コード分割・未使用コード削除・defer/async属性の使い分け
  • CSS最適化:未使用CSS削除・クリティカルCSSのインライン化・圧縮
  • Core Web Vitals:LCP(2.5秒以内)・INP(200ms以内)・CLS(0.1以下)の各目標値を達成する
  • サーバー最適化:HTTP/2有効化・Gzip/Brotli圧縮・長期キャッシュ・CDN活用
  • SEO・アクセシビリティ:適切なメタタグ・構造化データ・セマンティックHTML・ARIA属性・コントラスト比
  • 継続的監視:Lighthouse CIをGitHub Actionsに組み込んでPRごとに自動計測・品質維持

WithCodeで学んだWeb制作の基礎知識に、これらのパフォーマンス最適化技術を組み合わせれば、高速で高品質なWebサイトを構築できます。Lighthouseスコア100点は決してゴールではなく、ユーザーに快適な体験を提供するための手段です。まずは画像最適化から始め、継続的な改善を積み重ねていきましょう。


関連記事


参考リンク(公式・一次情報)


WithCodeを体験できる初級コース公開中!

WithCode初級コース

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    → 正しい学習方法で「確かな成長」を実感できるカリキュラム

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら
  • WithCareer
    - ウィズキャリ -

    就転職サポート

    大手エージェントのサポート下で
    キャリアアップを目指そう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次