「Webページの転送量の半分以上は画像だ」と佐藤CTOはデータを示した。「画像最適化だけで、ページロード時間を劇的に改善できる。」
1. 画像フォーマットの選択
| フォーマット | 用途 | 圧縮率 | ブラウザ対応 |
|---|---|---|---|
| WebP | 汎用(写真・イラスト) | JPEG比25-35%小さい | 97%+ |
| AVIF | 高品質写真 | JPEG比50%小さい | 92%+ |
| SVG | アイコン・ロゴ | ベクター(無限拡大) | 100% |
| PNG | 透過が必要な画像 | ロスレス | 100% |
<!-- picture要素で最適なフォーマットを提供 -->
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero" width="1200" height="600"
loading="eager" fetchpriority="high" decoding="async" />
</picture>
2. レスポンシブ画像
<!-- srcset + sizes でデバイスに最適なサイズを配信 -->
<img
srcset="
/product-400.webp 400w,
/product-800.webp 800w,
/product-1200.webp 1200w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
src="/product-800.webp"
alt="商品画像"
width="800" height="600"
loading="lazy"
decoding="async"
/>
画像CDNの活用
// Cloudflare Images / imgproxy 等で動的リサイズ
function getOptimizedImageUrl(
src: string,
width: number,
format: 'webp' | 'avif' = 'webp',
quality: number = 80
): string {
return `https://cdn.example.com/cdn-cgi/image/width=${width},format=${format},quality=${quality}/${src}`;
}
3. 遅延読み込み(Lazy Loading)
<!-- ネイティブ lazy loading -->
<img src="/product.webp" loading="lazy" alt="Product" width="400" height="300" />
<!-- 注意: LCP対象の画像には lazy loading を使わない! -->
<!-- Above-the-fold の画像は eager + fetchpriority="high" -->
// Intersection Observer による高度な制御
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target as HTMLImageElement;
img.src = img.dataset.src!;
observer.unobserve(img);
}
});
}, { rootMargin: '200px' }); // 200px手前でプリロード開始
4. フォント最適化
/* font-display で表示戦略を制御 */
@font-face {
font-family: 'NotoSansJP';
src: url('/fonts/NotoSansJP-Regular.woff2') format('woff2');
font-weight: 400;
font-display: swap; /* FOUT(Flash of Unstyled Text)を許容 */
unicode-range: U+3000-9FFF; /* 日本語のみ */
}
<!-- フォントのプリロード -->
<link rel="preload" href="/fonts/NotoSansJP-Regular.woff2"
as="font" type="font/woff2" crossorigin />
| font-display値 | 挙動 | 推奨場面 |
|---|---|---|
| swap | フォールバック即表示、ロード後切替 | 本文テキスト |
| optional | 極めて短い非表示期間、無ければフォールバック | 高パフォーマンス重視 |
| fallback | 短い非表示期間、中程度の切替期間 | バランス型 |
5. リソースヒント
<head>
<!-- preconnect: 事前にTCP/TLS接続を確立 -->
<link rel="preconnect" href="https://cdn.example.com" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<!-- dns-prefetch: DNS解決だけ先にやる -->
<link rel="dns-prefetch" href="https://analytics.example.com" />
<!-- preload: 高優先度リソースを早期にフェッチ -->
<link rel="preload" href="/critical.css" as="style" />
<link rel="preload" href="/hero.webp" as="image" />
<!-- prefetch: 次のナビゲーションで使うリソースを先読み -->
<link rel="prefetch" href="/products/popular.json" />
<!-- modulepreload: ESモジュールの先読み -->
<link rel="modulepreload" href="/js/checkout.js" />
</head>
まとめ
| トピック | 要点 |
|---|---|
| 画像フォーマット | WebP/AVIFを優先、picture要素でフォールバック |
| レスポンシブ画像 | srcset + sizes でデバイスに最適なサイズを配信 |
| 遅延読み込み | below-the-fold のみ lazy、LCP画像は eager |
| フォント | woff2 + font-display: swap + unicode-range |
| リソースヒント | preload/preconnect/prefetch で取得を最適化 |
チェックリスト
- WebP/AVIFの使い分けとフォールバック設定ができる
- srcset + sizes でレスポンシブ画像を実装できる
- lazy loadingの適切な使い所を判断できる
- フォント最適化(woff2, font-display, unicode-range)を適用できる
- リソースヒントの種類と使い分けを理解した
次のステップへ
画像・アセット最適化を学んだ。次は レンダリングパフォーマンス で、ブラウザの描画パイプラインを最適化しよう。
推定読了時間: 30分