MechaToraのブログ

記事のアイキャッチ画像
技術・開発

Web パフォーマンス最適化の実践 - サイトを爆速にする方法

「サイトの読み込みが遅い」「Lighthouseのスコアが低い」「ユーザーの離脱率が高い」——Webサイトのパフォーマンスは、ユーザー体験を左右する重要な要素です。Googleの調査によると、ページ読み込みが3秒以上かかると、53%のユーザーが離脱するとされています。

この記事では、MechaToraの15個のツールでLighthouseスコア90点以上を達成した経験から、実践的なパフォーマンス最適化手法を解説します。画像圧縮、遅延読み込み、CSS/JS最適化など、今すぐ使える技術をお伝えします。

パフォーマンスが重要な理由

3つの影響

MechaToraの改善実績

指標 最適化前 最適化後
Lighthouseスコア 72点 94点
読み込み時間 4.2秒 1.8秒
ページサイズ 3.5MB 850KB

Lighthouseでの測定

セクション画像

Lighthouseの使い方

  1. Chrome DevTools を開く(F12)
  2. Lighthouse タブを選択
  3. 「Analyze page load」をクリック

主要な指標

最適化1:画像の最適化

問題:画像が重すぎる

最適化前のMechaToraトップページ:

解決策1:画像圧縮

無料ツールで圧縮:

結果:2.8MB → 680KB(75%削減)

解決策2:次世代フォーマット(WebP)

<!-- 従来のJPEG -->
<img src="app-screenshot.jpg" alt="アプリ画面">

<!-- WebP対応(フォールバック付き) -->
<picture>
    <source srcset="app-screenshot.webp" type="image/webp">
    <source srcset="app-screenshot.jpg" type="image/jpeg">
    <img src="app-screenshot.jpg" alt="アプリ画面">
</picture>

WebPは同じ品質でJPEGより25〜35%小さくなります。

解決策3:遅延読み込み(Lazy Loading)

<!-- loading="lazy" を追加するだけ -->
<img src="large-image.jpg" alt="説明" loading="lazy">

<!-- 画面外の画像は必要になるまで読み込まれない -->

効果:初回読み込み時間が40%短縮

解決策4:レスポンシブ画像

<!-- 画面サイズに応じて適切なサイズの画像を配信 -->
<img
    srcset="app-320w.jpg 320w,
            app-640w.jpg 640w,
            app-1280w.jpg 1280w"
    sizes="(max-width: 640px) 100vw,
           (max-width: 1280px) 50vw,
           33vw"
    src="app-640w.jpg"
    alt="アプリ画面"
>

最適化2:CSS/JSの最適化

セクション画像

問題:レンダリングブロック

CSS/JSが全て読み込まれるまで、ページが表示されません。

解決策1:クリティカルCSSのインライン化

<!-- 最初に表示される部分のCSSをHTMLに直接記述 -->
<head>
    <style>
        /* クリティカルCSS(ファーストビューに必要な最小限のスタイル) */
        body {
            margin: 0;
            font-family: sans-serif;
        }
        .hero {
            background: #2563eb;
            color: white;
            padding: 2rem;
        }
    </style>

    <!-- 残りのCSSは非同期読み込み -->
    <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>

解決策2:JavaScriptの非同期読み込み

<!-- 悪い例:レンダリングブロック -->
<script src="app.js"></script>

<!-- 良い例1:defer(DOMの後に実行) -->
<script src="app.js" defer></script>

<!-- 良い例2:async(読み込み完了次第実行) -->
<script src="analytics.js" async></script>

使い分け:

解決策3:CSSの最小化

/* 最適化前(改行、スペース、コメント含む) */
.button {
    background-color: #2563eb;
    color: white;
    padding: 0.75rem 1.5rem;
    border-radius: 0.5rem;
}

/* 最適化後(1行、スペース削除) */
.button{background-color:#2563eb;color:white;padding:.75rem 1.5rem;border-radius:.5rem}

ツール:

最適化3:フォントの最適化

問題:Webフォントが重い

Google Fontsを読み込むと、数百KBのファイルをダウンロードします。

解決策1:font-display: swap

/* システムフォントを先に表示、Webフォント読み込み後に切り替え */
@font-face {
    font-family: 'Noto Sans JP';
    src: url('NotoSansJP.woff2') format('woff2');
    font-display: swap; /* これを追加 */
}

解決策2:必要な文字だけ読み込む

<!-- Google Fonts: 日本語サブセット -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap&subset=japanese" rel="stylesheet">

解決策3:システムフォントを使う

body {
    font-family:
        -apple-system,           /* macOS, iOS */
        BlinkMacSystemFont,      /* macOS Chrome */
        "Segoe UI",              /* Windows */
        "Helvetica Neue",
        "Hiragino Sans",         /* macOS日本語 */
        "Hiragino Kaku Gothic ProN", /* macOS日本語 */
        "Noto Sans CJK JP",      /* Linux日本語 */
        "Yu Gothic",             /* Windows日本語 */
        sans-serif;
}

Webフォント不要で、0バイト!

最適化4:キャッシュの活用

ブラウザキャッシュ

GitHub Pagesは自動的にキャッシュヘッダーを設定してくれます。自前サーバーの場合:

# .htaccess(Apache)
<IfModule mod_expires.c>
    ExpiresActive On

    # 画像:1年間キャッシュ
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"

    # CSS/JS:1ヶ月キャッシュ
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"

    # HTML:1時間キャッシュ
    ExpiresByType text/html "access plus 1 hour"
</IfModule>

Service Workerでのキャッシュ

// sw.js
const CACHE_NAME = 'mechatora-v1';
const urlsToCache = [
    '/',
    '/styles.css',
    '/app.js',
    '/images/logo.png'
];

self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => cache.addAll(urlsToCache))
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => response || fetch(event.request))
    );
});

最適化5:コンテンツ配信の最適化

CDNの活用

Cloudflare(無料)を使うと:

設定方法:

  1. Cloudflare でアカウント作成
  2. ドメインを追加
  3. ネームサーバーを変更
  4. 自動最適化をON(Speed → Optimization)

プリロード・プリフェッチ

<head>
    <!-- 重要なリソースを優先読み込み -->
    <link rel="preload" href="styles.css" as="style">
    <link rel="preload" href="app.js" as="script">

    <!-- 次に見るページを先読み -->
    <link rel="prefetch" href="about.html">
</head>

最適化6:HTMLの最適化

DOM要素を減らす

<!-- 悪い例:不必要なdivが多い -->
<div class="container">
    <div class="wrapper">
        <div class="inner">
            <div class="content">
                <p>テキスト</p>
            </div>
        </div>
    </div>
</div>

<!-- 良い例:必要最小限 -->
<div class="container">
    <p>テキスト</p>
</div>

HTMLの最小化

改行・スペース・コメントを削除:

<!-- 最適化前 -->
<html>
  <head>
    <title>MechaTora</title>
  </head>
  <body>
    <h1>見出し</h1>
  </body>
</html>

<!-- 最適化後 -->
<html><head><title>MechaTora</title></head><body><h1>見出し</h1></body></html>

実践:MechaToraの最適化プロセス

ステップ1:現状把握

# Lighthouseで測定
- Performance: 72点
- 主な問題: 画像が大きい、JSがブロッキング

ステップ2:画像最適化

ステップ3:CSS/JS最適化

ステップ4:再測定

# Lighthouse再測定
- Performance: 94点(+22点)
- 読み込み時間: 1.8秒(-2.4秒)

まとめ

優先度の高い最適化

  1. 画像圧縮:最も効果が大きい
  2. 遅延読み込み:loading="lazy"を追加するだけ
  3. JS/CSSの非同期読み込み:defer/async追加
  4. Webフォント最適化:font-display: swap

チェックリスト

パフォーマンス最適化は、一度やれば終わりではなく、継続的な改善が重要です。MechaToraでは、新しいツールを追加するたびにLighthouseで測定し、90点以上を維持しています。

まずは、画像圧縮とloading="lazy"から始めてみてください!