LESSON 30分

ストーリー

高橋アーキテクト
ページの総サイズが5MBある。そのうち4MBが画像だ

高橋アーキテクトがDevToolsのネットワークタブを示した。

高橋アーキテクト
画像はWebサイトの転送量の50-80%を占める。画像を最適化するだけで、ページ読み込み時間が半分以下になることも珍しくない

画像フォーマットの選択

フォーマット用途圧縮透過サイズ比較
JPEG写真、複雑な画像非可逆なし基準
PNGロゴ、アイコン可逆あり2-5倍大
WebP写真全般両対応あり25-35%小
AVIF写真全般(次世代)非可逆あり40-50%小
SVGアイコン、図形テキストあり極小

レスポンシブ画像

<!-- picture要素で最適なフォーマットを選択 -->
<picture>
  <!-- AVIF対応ブラウザにはAVIFを配信 -->
  <source
    type="image/avif"
    srcset="product-400w.avif 400w,
            product-800w.avif 800w,
            product-1200w.avif 1200w"
    sizes="(max-width: 600px) 400px,
           (max-width: 1200px) 800px,
           1200px"
  >
  <!-- WebP対応ブラウザにはWebPを配信 -->
  <source
    type="image/webp"
    srcset="product-400w.webp 400w,
            product-800w.webp 800w,
            product-1200w.webp 1200w"
    sizes="(max-width: 600px) 400px,
           (max-width: 1200px) 800px,
           1200px"
  >
  <!-- フォールバック -->
  <img
    src="product-800w.jpg"
    alt="商品画像"
    width="800"
    height="600"
    loading="lazy"
  >
</picture>

画像最適化のテクニック

1. 適切なサイズ

// 画像リサイズのパイプライン
interface ImageResizeConfig {
  breakpoints: {
    thumbnail: { width: 150, height: 150 };
    small: { width: 400 };
    medium: { width: 800 };
    large: { width: 1200 };
    original: { width: null }; // リサイズしない
  };
  quality: {
    webp: 80;
    avif: 65;
    jpeg: 85;
  };
}

// sharp を使った画像処理の例
async function optimizeImage(
  inputPath: string,
  outputDir: string
): Promise<string[]> {
  const sizes = [400, 800, 1200];
  const formats = ['webp', 'avif', 'jpeg'];
  const outputs: string[] = [];

  for (const size of sizes) {
    for (const format of formats) {
      const output = `${outputDir}/image-${size}w.${format}`;
      await sharp(inputPath)
        .resize(size)
        .toFormat(format, { quality: format === 'avif' ? 65 : 80 })
        .toFile(output);
      outputs.push(output);
    }
  }

  return outputs;
}

2. 圧縮

// 画像圧縮の効果(例: 1200×800の商品写真)
const compressionResults = {
  original:  { format: 'JPEG', size: '450KB', quality: 100 },
  optimized: { format: 'JPEG', size: '120KB', quality: 85 },
  webp:      { format: 'WebP', size: '85KB',  quality: 80 },
  avif:      { format: 'AVIF', size: '55KB',  quality: 65 },
  // 元画像の88%を削減(450KB → 55KB)
};

3. プレースホルダー(LQIP)

// Low Quality Image Placeholder
// ぼやけた極小画像を先に表示し、本画像の読み込みを待つ
const lqipConfig = {
  placeholder: {
    width: 20,         // 20px幅の極小画像
    quality: 20,       // 低品質
    blur: true,        // CSSでぼかし
    size: '500bytes',  // インラインBase64で埋め込み可能
  },
};
<!-- LQIP の実装例 -->
<div class="image-container">
  <img
    src="data:image/webp;base64,UklGR..."
    data-src="product-800w.webp"
    alt="商品画像"
    class="lazy-image blur"
    width="800"
    height="600"
  >
</div>

<style>
.lazy-image.blur {
  filter: blur(20px);
  transition: filter 0.3s;
}
.lazy-image.loaded {
  filter: blur(0);
}
</style>

フォントの最適化

// Webフォント最適化
const fontOptimization = {
  // 1. font-display: swap で描画をブロックしない
  cssRule: `
    @font-face {
      font-family: 'NotoSansJP';
      src: url('/fonts/NotoSansJP.woff2') format('woff2');
      font-display: swap;
      unicode-range: U+3000-9FFF; /* 日本語の範囲のみ */
    }
  `,

  // 2. preload でフォントを先読み
  preload: '<link rel="preload" href="/fonts/NotoSansJP.woff2" as="font" type="font/woff2" crossorigin>',

  // 3. サブセット化(使用する文字のみ含める)
  subset: '不要な文字を除去してファイルサイズを80%削減',
};

CSS/JSの最適化

技法説明効果
Minification空白・コメント除去20-40%削減
Compressiongzip/brotli圧縮さらに60-80%削減
Critical CSS初期表示に必要なCSSをインライン化レンダリングブロック回避
Preconnect外部ドメインへの事前接続DNS+TCP+TLS時間を節約
<!-- Critical CSS のインライン化 -->
<head>
  <!-- 初期表示に必要なCSSをインライン -->
  <style>
    .header { background: #1e293b; color: white; padding: 16px; }
    .hero { min-height: 400px; display: flex; align-items: center; }
  </style>
  <!-- 残りのCSSは非同期読み込み -->
  <link rel="preload" href="/css/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

  <!-- 外部ドメインへの事前接続 -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://cdn.example.com">
</head>

まとめ

ポイント内容
画像フォーマットWebP/AVIFを優先、フォールバックにJPEG
レスポンシブ画像デバイスに応じたサイズ・フォーマットを配信
圧縮適切なquality設定で80-90%削減可能
フォントサブセット化 + font-display: swap
CSS/JSMinification + Compression + Critical CSS

チェックリスト

  • 画像フォーマットの使い分けを理解した
  • レスポンシブ画像の実装方法を把握した
  • LQIPの概念と実装を理解した
  • フォントとCSS/JSの最適化手法を知った

次のステップへ

次は「CDNとエッジコンピューティング」を学びます。コンテンツをユーザーの近くから配信し、グローバルなパフォーマンスを向上させる方法です。


推定読了時間: 30分