言語を切り替える
テーマを切り替える

Astro画像最適化完全ガイド:サイト読み込みを50%速くする5つの実践テクニック

先月 Astro で技術ブログを立ち上げ、うきうきと公開したら——ファーストビューの読み込みに 6 秒 もかかったのです。画像は 2〜3MB 当たり、スマホではコンテンツが見えるまでさらに待たされます。正直、性能がひどすぎて唖然としました。

その後 2 日かけて Astro の画像最適化を調べ、Image コンポーネントの設定からフォーマット選定、遅延読み込み、CDN 連携まで順に手を入れました。ファーストビューは 1.8 秒 まで短縮され、Lighthouse のパフォーマンススコアは 62 点から 95 点 へ。95 点を見たときは、本当にうれしかったです。

本記事では、その間に踏んだ落とし穴とまとめたノウハウをすべて共有します。内容は次のとおりです。

  • Astro Image コンポーネントをゼロから設定する完全なコード例
  • JPEG・PNG・WebP・AVIF の4フォーマットの選び方
  • 遅延読み込みのベストプラクティス
  • Cloudflare CDN 連携の詳細手順
  • よくある問題の切り分け方法

読み終える頃には、あなたの Astro サイトの読み込み速度も 50% 以上 改善できるはずです。では始めましょう。

なぜ Astro の画像最適化が重要なのか

「画像最適化なんて、数秒待てばいいでしょ」と思う人もいるかもしれません。しかし 画像は Web ページ全体の 60〜70% を占め、パフォーマンスを落とす最大の要因です。

以前のブログでは、未圧縮のカバー画像1枚が 2.5MB、記事内のスクリーンショットを足すとページ全体が 5〜6MB になりがちでした。ユーザーは画像の読み込みだけで数秒待ち、直帰率も高止まりしていました。

Google の画像読み込み要件

Google の Core Web Vitals には LCP(Largest Contentful Paint/最大コンテンツの描画) があります。ページの主要コンテンツが表示されるまでの時間で、2.5 秒以内 が目安、4 秒を超えると評価が下がります。

多くのサイトでは LCP は大きなカバー画像やファーストビューの画像そのものです。画像が遅いと LCP が悪化し、SEO にも影響します。

実際の最適化効果

最適化前後のデータを整理しました。

最適化前:

  • ファーストビュー読み込み: 6.2 秒
  • Lighthouse パフォーマンス: 62 点
  • 画像合計: 約 8MB
  • LCP: 4.8 秒
71%
読み込み時間の短縮
6.2秒→1.8秒
62→95点
Lighthouse向上
パフォーマンススコア53%向上
85%
画像サイズ削減
8MB→1.2MB
1.8秒
ファーストビュー読み込み時間
6.2秒から1.8秒へ。Lighthouseスコアは62点から95点に向上

最適化後:

  • ファーストビュー読み込み: 1.8 秒(約 70% 改善)
  • Lighthouse パフォーマンス: 95 点(約 53% 向上)
  • 画像合計: 約 1.2MB(約 85% 削減)
  • LCP: 1.3 秒(約 73% 改善)

想定以上の効果でした。直帰率は約 35% 低下 し、コンテンツを読み進めるユーザーが明らかに増えました。

Astro はもともとパフォーマンス重視のフレームワークです。画像最適化のせいでその強みを損なうのはもったいない。ここからは、画像最適化を一つずつ進めていきます。

Astro Image コンポーネント完全ガイド

Astro には <Image /><Picture /> が組み込まれており、画像最適化専用です。初めて公式ドキュメントを読んだときは、widths・quality・inferSize が何のためかよくわかりませんでした。実際に試してようやく理解できました。

基本:ImagePicture

まず <Image /> です。最もよく使います。

---
import { Image } from 'astro:assets';
import coverImage from '../assets/blog-cover.jpg';
---

<Image
  src={coverImage}
  alt="ブログのカバー画像"
  width={1200}
  height={630}
/>

このコンポーネントが自動で行うこと:

  • 画像の圧縮
  • WebP への変換(デフォルト)
  • レスポンシブ画像の生成
  • 読み込みパフォーマンスの最適化

次に <Picture /> です。複数フォーマットのフォールバックに向いています。

---
import { Picture } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---

<Picture
  src={heroImage}
  formats={['avif', 'webp', 'jpeg']}
  alt="ヒーロー画像"
  width={1920}
  height={1080}
/>

ブラウザは AVIF(最小)を優先し、非対応なら WebP、さらにダメなら JPEG へと段階的に読み込みます。性能と互換性の両立ができます。

主要プロパティの解説

最初は設定に迷いましたが、何度か試してコツが掴めました。

widths — レスポンシブ幅

<Image
  src={image}
  widths={[400, 800, 1200]}
  sizes="(max-width: 768px) 400px, (max-width: 1024px) 800px, 1200px"
  alt="レスポンシブ画像"
/>

この設定で Astro は 3 サイズを生成し、画面幅に応じて最適なものを選びます。モバイルは小さく、デスクトップは大きく——通信量を抑えつつ速く表示できます。

quality — 画質制御

<Image
  src={image}
  quality="mid"  // 数値も可: quality={80}
  alt="ブログの挿絵"
/>
  • low: サムネイル・背景向け
  • mid: 多くの場面で十分(推奨)
  • high: 高画質が必要な場面
  • 数値(0〜100): 細かく調整

私は mid80 を使うことが多く、見た目の差はほぼなく、ファイルサイズは 30〜40% 減ります。

inferSize — リモート画像向け

<Image
  src="https://example.com/image.jpg"
  inferSize={true}
  alt="リモート画像"
/>

リモート画像でサイズが不明なとき、inferSize を付けると Astro が自動取得します。何度も助けられました。

loading — 遅延読み込み

<!-- ファーストビュー:即時読み込み -->
<Image src={hero} loading="eager" alt="ファーストビュー画像" />

<!-- ファーストビュー以下:遅延読み込み -->
<Image src={content} loading="lazy" alt="本文の画像" />

format — 出力フォーマット

<Image
  src={image}
  format="webp"  // webp | avif | jpeg | png
  alt="指定フォーマット"
/>

ローカル画像とリモート画像

しばらく迷っていましたが、整理はシンプルです。

ローカル画像(推奨)

---
// src/assets/ または src/images/ に配置
import myImage from '../assets/photo.jpg';
---
<Image src={myImage} alt="ローカル画像" />

ローカル画像は Astro が自動で最適化・圧縮・バンドルします。可能ならこちらを使ってください。

リモート画像

---
// astro.config.mjs で許可ドメインの設定が必要
---
<Image
  src="https://images.unsplash.com/photo-xxx"
  width={800}
  height={600}
  alt="リモート画像"
/>

astro.config.mjs の設定例:

export default defineConfig({
  image: {
    domains: ['images.unsplash.com', 'cdn.example.com']
  }
});

public ディレクトリの画像

<!-- public/logo.png → /logo.png -->
<img src="/logo.png" alt="ロゴ" />

public/ に置いた画像は 最適化されません。ロゴや favicon など小さなファイル向けです。

実践コード例

ブログで実際に使っている設定です。

ブログカバー(ファーストビュー・プリロード)

---
import { Image } from 'astro:assets';
import coverImage from '../assets/blog-cover.jpg';
---

<Image
  src={coverImage}
  alt="Astro画像最適化完全ガイド"
  width={1200}
  height={630}
  format="webp"
  quality={85}
  loading="eager"
  class="blog-cover"
/>

記事内画像(遅延読み込み)

<Image
  src={screenshot}
  alt="設定例のスクリーンショット"
  width={800}
  height={450}
  format="webp"
  quality="mid"
  loading="lazy"
/>

著者アバター(小さなアイコン・プリロード)

<Image
  src={avatar}
  alt="著者のアバター"
  width={48}
  height={48}
  format="webp"
  loading="eager"
/>

Image コンポーネントの話はここまで。次は、多くの人が悩む画像フォーマットの選び方です。

画像フォーマット選択完全ガイド

「JPEG・PNG・WebP・AVIF、結局どれ?」——最初は私も混乱していました。実際に比較して、それぞれの向き不向きがはっきりしました。

4つの主要フォーマット比較

フォーマット圧縮ファイルサイズブラウザ対応向いている用途
JPEG非可逆中程度100%写真・複雑な画像
PNG可逆大きめ100%透明度が必要な画像
WebP非可逆/可逆小さい97%+汎用(推奨)
AVIF非可逆/可逆最小90%+極限まで圧縮したい場合

JPEG — 定番で互換性最高

  • メリット: 全ブラウザ対応、そこそこ圧縮できる
  • デメリット: 透明度非対応、WebP より圧縮率は劣る
  • 向き: ブログ挿絵、商品写真、人物写真

PNG — 可逆・透明度対応

  • メリット: 画質劣化なし、透明度あり
  • デメリット: ファイルが大きい(JPEG の 2〜3 倍になりがち)
  • 向き: ロゴ、アイコン、透明背景

WebP — Google 推奨、バランス良好

  • メリット: JPEG より約 30% 小さい、透明度対応、互換性も高い
  • デメリット: ごく一部の古いブラウザ非対応(2025 年時点では稀)
  • 向き: ほとんどの場面。私の第一候補

AVIF — 最新で圧縮率最高

  • メリット: WebP よりさらに 20〜30% 小さい、画質も良好
  • デメリット: 対応ブラウザがやや少ない、エンコードが遅い
  • 向き: パフォーマンス最優先の場面

フォーマット選択のフロー

細かい比較表が面倒なら、この流れで十分です。

透明度が必要?
├─ はい → WebP(第一候補)または PNG(フォールバック)
└─ いいえ → 続行

写真や複雑な画像?
├─ はい → WebP(第一候補)または AVIF(極限追求)
└─ いいえ → 続行

ロゴやアイコン?
├─ はい → SVG(ベクター)
└─ いいえ → 続行

アニメーション?
└─ WebP(GIF の代替)

経験上、90% の場面は WebP で足ります。互換性・圧縮率・手間のバランスが良いからです。

互換性への配慮

AVIF を使いつつ古いブラウザも気にするなら、<Picture> でフォールバックを用意します。

---
import { Picture } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---

<Picture
  src={heroImage}
  formats={['avif', 'webp', 'jpeg']}
  alt="ヒーロー画像"
  width={1920}
  height={1080}
/>

読み込みの流れ:

  1. まず AVIF(最小・最新)
  2. 非対応なら WebP(次に小さい・互換性良好)
  3. それでもダメなら JPEG(最大・100% 互換)

モダンブラウザには最良の体験を、古い環境にも破綻しない表示を届けられます。

圧縮率の実測比較

2.5MB の原図で試しました。

フォーマットファイルサイズ圧縮率見た目の品質
原図(PNG)2.5MB-オリジナル
JPEG(quality=85)450KB82%肉眼ではほぼ差なし
WebP(quality=85)180KB93%肉眼ではほぼ差なし
AVIF(quality=85)120KB95%肉眼ではほぼ差なし

同じ見た目でも、WebP は JPEG より約 60% 小さく、AVIF は約 73% 小さい。効果ははっきりしています。

私のおすすめ:

  • 日常利用: WebP(互換性と圧縮率のバランス)
  • 極限追求: AVIF + WebP + JPEG の三段フォールバック
  • 透明度: WebP 優先、必要なら PNG
  • ロゴ・アイコン: 可能なら SVG(拡大しても劣化しない)

フォーマットの話はここまで。次は遅延読み込み——設定次第でファーストビューが大きく変わります。

遅延読み込みのベストプラクティス

遅延読み込み(Lazy Loading)は、「見えるタイミングで読み込む」仕組みです。ビューポート外の画像は後回しにし、スクロールで近づいたら読み込みます。ファーストビューの時間を大きく短縮できます。

遅延読み込みの仕組み

現行ブラウザは loading 属性でネイティブ対応しています。

<img src="image.jpg" loading="lazy" alt="遅延読み込み画像" />

Astro の Image コンポーネントはデフォルトで遅延読み込みです。細かく制御する場合:

<!-- 遅延読み込み(デフォルト) -->
<Image src={image} loading="lazy" alt="遅延読み込み" />

<!-- 即時読み込み -->
<Image src={image} loading="eager" alt="即時読み込み" />

ブラウザは Intersection Observer API で画像がビューポートに入るか監視し、入りそうになったタイミングで読み込みを開始します。

遅延読み込みの設計方針

重要なのは どの画像を遅延し、どれを即時にするか です。

即時読み込み(loading=“eager”):

  • ファーストビューに見える画像(ヒーロー、カバー)
  • ロゴ、ナビのアイコン
  • 重要なビジネス画像(メイン商品、プロフィール)
  • Above the fold(最初の画面)のすべて

遅延読み込み(loading=“lazy”):

  • ファーストビュー以下の本文画像
  • 記事内の挿絵・スクリーンショット
  • 一覧のサムネイル
  • フッター画像
  • 装飾目的の画像

私の経験では、ファーストビューは 1〜2 枚だけ即時、それ以外はすべて遅延で十分です。最初の画面は速く、一度に読む画像数も抑えられます。

実践設定例

ブログでの実際の設定です。

ブログトップ

---
import { Image } from 'astro:assets';
---

<!-- ヒーローカバー:即時 -->
<Image
  src={heroCover}
  loading="eager"
  alt="ブログトップのカバー"
  width={1920}
  height={1080}
/>

<!-- 記事一覧サムネイル:遅延 -->
{posts.map(post => (
  <Image
    src={post.thumbnail}
    loading="lazy"
    alt={post.title}
    width={400}
    height={225}
  />
))}

記事詳細

<!-- 記事上部のカバー:即時 -->
<Image
  src={article.cover}
  loading="eager"
  alt={article.title}
  width={1200}
  height={630}
/>

<!-- 本文内の画像:すべて遅延 -->
<Image
  src={screenshot1}
  loading="lazy"
  alt="コード例のスクリーンショット"
  width={800}
  height={450}
/>

<Image
  src={screenshot2}
  loading="lazy"
  alt="効果比較の画像"
  width={800}
  height={450}
/>

ギャラリー(特殊ケース)

<!-- 最初の6枚は即時 -->
{gallery.slice(0, 6).map(img => (
  <Image src={img} loading="eager" alt={img.alt} />
))}

<!-- それ以降は遅延 -->
{gallery.slice(6).map(img => (
  <Image src={img} loading="lazy" alt={img.alt} />
))}

パフォーマンスの計測

最適化後、効果を確認するツールです。

1. Lighthouse(Chrome DevTools)

F12 → Lighthouse → 「Analyze page load」:

  • Performance: 90 点以上が目安
  • LCP: 2.5 秒以内
  • CLS: 0 に近い(レイアウトシフト防止)

最適化前は Performance 62 点・LCP 4.8 秒、最適化後は Performance 95 点・LCP 1.3 秒でした。

2. Chrome DevTools の Network

F12 → Network → 「Disable cache」にチェック → 再読み込み:

  • ウォーターフォールで画像の読み込み順序を確認
  • ファーストビュー画像が優先されているか
  • 遅延画像がスクロール時に読み込まれているか

3. WebPageTest

実ユーザーの環境に近い計測なら WebPageTest で地域・デバイス別の結果を確認できます。

最適化前後の比較:

指標最適化前最適化後改善
ファーストビュー読み込み6.2秒1.8秒71%
LCP4.8秒1.3秒73%
ファーストビュー画像合計8MB1.2MB85%
Performance スコア62点95点53%

体感でもかなり違います。

遅延読み込みが整ったら、CDN でグローバルな配信速度を上げましょう。

画像 CDN 連携の実践

最初は「CDN は設定が面倒で高そう」と思っていました。Cloudflare の無料枠で足りること、設定もそこまで難しくないことを知り、導入しました。

CDN が必要な理由

CDN(Content Delivery Network)は、画像を世界各地のエッジにキャッシュし、ユーザーは最寄りのノードから取得します。

CDN のメリット:

  • グローバル高速化: 東京のユーザーは東京ノード、ニューヨークのユーザーはニューヨークノードから
  • オリジン負荷軽減: 画像リクエストの多くが CDN 側へ
  • 自動最適化: フォーマット変換や圧縮を CDN が担うことも
  • 冗長性: 1 ノード障害でも他ノードで配信継続

Cloudflare CDN 導入後、海外からのアクセスは読み込みが約 60% 速く なりました。

Cloudflare Image Resizing の連携

Cloudflare の Image Resizing は Astro と相性が良いです。

ステップ1: Cloudflare Image Resizing を有効化

Cloudflare Dashboard → ドメイン選択 → Speed → Optimization → 「Image Resizing」をオン

無料プランは月 5 万回の変換まで。個人ブログなら十分です。

ステップ2: astro.config.mjs の設定

import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server', // または 'hybrid'
  adapter: cloudflare({
    imageService: 'cloudflare' // Cloudflare 画像サービスを使用
  }),
  image: {
    // リモート画像を使う場合の許可ドメイン
    domains: ['images.unsplash.com', 'cdn.example.com']
  }
});

ステップ3: 許可ドメイン(リモート画像利用時)

外部 CDN の画像を使う場合は image.domains に追加します。

export default defineConfig({
  image: {
    domains: [
      'images.unsplash.com',
      'cdn.example.com',
      'res.cloudinary.com'
    ]
  }
});

設定後、Astro の Image コンポーネントは Cloudflare の画像サービスで最適化されます。

その他の CDN 案

Cloudflare 以外にも選択肢があります。

Cloudinary

画像 CDN 専門で Astro SDK もあります。

npm install @cloudinary/url-gen
---
import { CldImage } from 'astro-cloudinary';
---

<CldImage
  src="sample"
  width={800}
  height={600}
  alt="Cloudinaryの画像"
/>

変換・フィルター・ウォーターマークなど機能は豊富ですが、無料枠を超えると有料になります。

Uploadcare

アップロードと処理がしやすい画像 CDN です。

// astro.config.mjs
export default defineConfig({
  image: {
    service: {
      entrypoint: 'uploadcare-astro',
      config: {
        publicKey: 'your-public-key'
      }
    }
  }
});

Cloudflare R2

画像が非常に多い場合は R2 でオブジェクトストレージも検討できます。

// astro.config.mjs
export default defineConfig({
  build: {
    assetsPrefix: 'https://your-r2-domain.com'
  }
});

R2 は転送料が無料で、ストレージ課金のみ。コスト面でも有利です。

CDN 設定の注意点

私が踏んだ落とし穴です。

1. SSR ではドメインごとに最適化を有効化

SSR(Server-Side Rendering)利用時は、Cloudflare Dashboard で各ドメインの Image Resizing をオンにしてください。

2. リモート画像は許可ドメイン必須

未設定だと次のエラーになります。

Image's component src parameter is not allowed for this image.

astro.config.mjsimage.domains にドメインを追加してください。

3. compile モードはビルド時のみ最適化

adapter: cloudflare({
  imageService: 'compile' // ビルド時のみ最適化
})

パッケージ時に一度だけ最適化し、実行時は再処理しません。純静的サイト向けです。

4. 無料枠に注意

CDN サービス無料枠超過料金
Cloudflare Image Resizing5万回/月$5/5万回
Cloudinary25 credits/月従量課金
Uploadcare3GB 保存 + 3GB 転送従量課金
Cloudflare R210GB 保存$0.015/GB/月

個人ブログなら無料枠で足りることが多いです。商用はコスト設計が必要です。

コスト比較の例:

月間 PV 約 2 万、画像リクエスト約 10 万のブログ:

  • Cloudflare: 無料枠内(5 万回まで)
  • Cloudinary: 有料($9/月〜)
  • Uploadcare: 有料($25/月〜)

私は Cloudflare を選びました。コストと使いやすさのバランスが良いからです。

CDN の話はここまで。最後に、よくあるトラブルの切り分けです。

よくある問題とトラブルシューティング

ここでは私が踏んだ問題をまとめます。同じ轍を踏まない助けになれば幸いです。

画像が表示されない

症状: 空白、または壊れた画像アイコン。

原因と対処:

1. import パスが間違っている

// ❌ 相対パスの階層ミス
import image from './assets/photo.jpg';

// ✅ 正しい階層を確認
import image from '../assets/photo.jpg';

2. リモート画像の許可ドメイン未設定

// astro.config.mjs
export default defineConfig({
  image: {
    domains: ['images.unsplash.com'] // 忘れずに追加
  }
});

典型的なエラー:

Image's component src parameter is not allowed for this image.

3. 非対応フォーマット

Astro が扱える形式: JPG, JPEG, PNG, WEBP, AVIF, GIF, SVG

TIFF や BMP は事前に JPG/PNG へ変換してください。

画像がぼやける・画質が悪い

症状: 表示がにじむ、明らかな劣化。

対処:

1. quality の調整

<!-- 画質が低すぎる -->
<Image src={img} quality="low" alt="ぼやけた例" />

<!-- 画質を上げる -->
<Image src={img} quality={85} alt="くっきりした例" />

2. 原解像度不足

原図が 400×300 なのに 1200×900 で表示すれば当然ぼけます。高解像度の原図を用意してください。

3. レスポンシブサイズ不足

<!-- ❌ サイズが小さすぎる -->
<Image
  src={img}
  widths={[200, 400]}
  sizes="(max-width: 1920px) 400px"
  alt="デスクトップでは粗くなる"
/>

<!-- ✅ 十分なサイズを用意 -->
<Image
  src={img}
  widths={[400, 800, 1200, 1920]}
  sizes="(max-width: 768px) 400px, (max-width: 1024px) 800px, 1200px"
  alt="各画面で鮮明"
/>

ビルド時エラー

症状: npm run build で画像関連エラー。

1. Sharp のインストール失敗

エラー例:

Error: Could not load the "sharp" module

対処:

# node_modules を削除して再インストール
rm -rf node_modules package-lock.json
npm install

# または sharp だけ再インストール
npm uninstall sharp
npm install sharp

それでもダメなら特定バージョン:

npm install [email protected]

2. メモリ不足

エラー例:

FATAL ERROR: Reached heap limit Allocation failed

対処: Node.js のヒープを増やす

# package.json
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=4096' astro build"
  }
}

3. 非対応フォーマット

HEIC や TIFF は Sharp で処理できないことがあります。事前に JPG/PNG へ変換してください。

SSR モードでの画像問題

症状: ローカルでは表示されるが、Cloudflare Pages/Workers デプロイ後に表示されない。

対処:

1. imageService の設定

// astro.config.mjs
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server',
  adapter: cloudflare({
    imageService: 'cloudflare' // 必須
  })
});

2. output モードの確認

export default defineConfig({
  output: 'server', // または 'hybrid'
  // output: 'static' では Cloudflare imageService は使えない
});

3. ローカル画像の配置場所

SSR ではローカル画像は src/ 配下に置き、public/ 直リンクは最適化されません。

---
// ✅ 正しい: src/assets/
import image from '../assets/photo.jpg';

// ❌ public/ は最適化されない
// <img src="/photo.jpg" />
---

<Image src={image} alt="正しい使い方" />

トラブルシューティングチェックリスト

問題が出たら、この順で確認してください。

  1. ✓ import パスは正しいか
  2. ✓ 画像フォーマットは対応しているか
  3. ✓ リモート画像のドメインは許可リストにあるか
  4. ✓ quality は妥当か
  5. ✓ Sharp は正しくインストールされているか
  6. ✓ SSR 設定(imageService など)は正しいか
  7. ✓ ブラウザ Console にエラーはないか
  8. ✓ Network タブで画像リクエストの状態を確認したか

ここまで来たら、まとめに入りましょう。

まとめ

Astro の画像最適化に 2 日かけて得た知見を、同じ悩みのある方のために書きました。

核心は次の5点です。

  1. Image コンポーネント: <img> の代わりに <Image /> を使い、圧縮・フォーマット変換・レスポンシブを自動化
  2. フォーマット: 90% は WebP で十分。極限なら AVIF フォールバック、透明度は WebP か PNG
  3. 遅延読み込み: ファーストビューは 1〜2 枚だけ即時、他は lazy で初期読み込みを 50% 以上削減
  4. CDN: Cloudflare なら無料枠で個人ブログは足り、海外アクセスは約 60% 高速化
  5. トラブルシューティング: チェックリスト順に確認。9 割はパス・設定・Sharp の問題

最適化後、ファーストビューは 6.2 秒→1.8 秒、Lighthouse は 62→95、直帰率は約 35% 低下。投資対効果は非常に高いです。

今すぐできること:

  • サイトを開き、F12 で Lighthouse を実行し、現状のスコアを把握する
  • 画像フォーマットを見直し、WebP に置き換えられるものは置き換える
  • ファーストビュー以外に loading="lazy" を付ける
  • 画像が多ければ Cloudflare CDN の導入を検討する

画像最適化は一度で終わる作業ではありません。少しずつ進めれば、性能も体験も確実に良くなります。

最適化後に疑問があったり、より良いやり方があれば、コメントでぜひ教えてください。サイトがどんどん速くなることを願っています。

Astro画像最適化完全ガイド:サイト読み込みを50%速くする

5つの実践テクニックでファーストビュー読み込みを6秒から1.8秒へ、Lighthouseスコアを62点から95点へ

⏱️ 目安時間: 2 時間

  1. 1

    ステップ1: 画像最適化の重要性と目標を理解する

    画像最適化の重要性:
    • 画像はWebページ全体の60〜70%を占め、パフォーマンス低下の最大要因
    • 以前のブログでは、未圧縮のカバー画像1枚が2.5MB
    • 記事内のスクリーンショットを足すとページ全体が5〜6MBになりがち
    • ユーザーは画像の読み込みだけで数秒待ち、直帰率が高くなる

    Googleの画像読み込み要件:
    • Core Web VitalsのLCP(Largest Contentful Paint/最大コンテンツの描画)
    • ページの主要コンテンツが表示されるまでの時間
    • GoogleはLCPを2.5秒以内とし、4秒超は評価が下がる
    • 多くのサイトではLCPは大きなカバー画像やファーストビュー画像
    • 画像が遅いとLCPが悪化し、SEOに影響する

    最適化目標:
    • ファーストビュー読み込み6.2秒→1.8秒(71%改善)
    • Lighthouseパフォーマンス62点→95点(53%向上)
    • 画像合計約8MB→約1.2MB(85%削減)
    • LCP 4.8秒→1.2秒(75%改善)
  2. 2

    ステップ2: テクニック1:Astro Imageコンポーネントを使う

    Astro Imageコンポーネントの利点:
    • 画像フォーマット・サイズ・遅延読み込みを自動最適化
    • <img>の代わりに<Image />を使用
    • 圧縮・フォーマット変換・レスポンシブ処理を自動化

    設定手順:
    1. @astrojs/image統合をインストール(npx astro add image を実行)
    2. astro.config.mjsでimageServiceを設定(sharpまたはsquooshを選択)
    3. Imageコンポーネントを使用:
    import { Image } from 'astro:assets';
    <Image src={image} alt="説明" />

    ローカル画像のパス:
    • SSRモードではローカル画像はsrc/配下に置き、public/直リンクは最適化されない
    • 正しい例:import image from '../assets/photo.jpg'; <Image src={image} alt="正しい使い方" />
    • 誤り:public/の画像は最適化されない
  3. 3

    ステップ3: テクニック2〜3:適切なフォーマット選択と遅延読み込み

    フォーマット選択:
    • JPEG:写真・複雑な画像向け、互換性最高
    • PNG:アイコン・透明背景向け、ファイルは大きめ
    • WebP:JPEGより30〜50%小さい、モダンブラウザ対応、90%の場面でWebPで十分
    • AVIF:WebPよりさらに20〜30%小さい、最新フォーマット、互換性はやや低い、極限追求ならAVIFフォールバック

    遅延読み込みの設定:
    • ファーストビューは1〜2枚だけ即時読み込み、他はすべて遅延
    • 初期読み込み量を50%以上削減できる
    • loading="lazy"属性、またはImageコンポーネントのloadingプロパティを使用
  4. 4

    ステップ4: テクニック4〜5:CDN高速化と画像サイズ最適化

    Cloudflare CDN連携:
    • Cloudflare ImagesまたはR2ストレージを利用
    • 自動最適化とフォーマット変換を設定
    • 世界300以上のエッジで加速、個人利用は無料枠で十分なことが多い
    • 実測でレイテンシが大幅に短縮

    設定手順:
    1. Cloudflare DashboardでImagesまたはR2を有効化
    2. imageServiceでCloudflareを指定
    3. 画像をCloudflareに配置
    4. Cloudflare URLで画像を読み込む

    画像サイズの最適化:
    • srcsetとsizesでデバイスに応じたサイズを配信
    • Imageコンポーネントのwidthとheightで適切な寸法を指定
  5. 5

    ステップ5: トラブルシューティングとベストプラクティス

    トラブルシューティングチェックリスト:
    1. importパスが正しいか確認
    2. 画像フォーマットが対応しているか確認
    3. リモート画像ドメインが許可リストにあるか確認
    4. qualityパラメータが妥当か確認
    5. Sharpが正しくインストールされているか確認

    よくある問題:
    • Sharpインストール失敗 → Nodeバージョンを確認し、npm install sharpを実行
    • リモート画像の最適化失敗 → ドメイン許可リストを確認
    • SSRモード非対応 → outputを'server'または'hybrid'に設定

    ベストプラクティス:
    • 画像最適化は継続的な作業。一度に全部やらなくてよい
    • 少しずつ進めれば、性能も体験も確実に向上する

    今すぐできること:
    1. サイトを開き、F12でLighthouseを実行し、現状のスコアを確認
    2. 画像フォーマットを見直し、WebPに置き換えられるものは置き換える
    3. ファーストビュー以外にloading="lazy"を付ける
    4. 画像が多ければCloudflare CDNの導入を検討

FAQ

なぜ画像最適化が重要なのですか?
画像最適化の重要性:
• 画像はWebページ全体の60〜70%を占め、パフォーマンス低下の最大要因
• 以前のブログでは未圧縮のカバー画像1枚が2.5MB、記事内スクリーンショットを足すと5〜6MBになりがち
• ユーザーは画像の読み込みだけで数秒待ち、直帰率が高くなる

Googleの画像読み込み要件:
• Core Web VitalsのLCP(Largest Contentful Paint/最大コンテンツの描画)
• ページの主要コンテンツが表示されるまでの時間
• GoogleはLCPを2.5秒以内とし、4秒超は評価が下がる
• 多くのサイトではLCPは大きなカバー画像やファーストビュー画像
• 画像が遅いとLCPが悪化し、SEOに影響する
Astroの画像最適化の効果はどのくらいですか?
最適化効果:
• ファーストビュー読み込み6.2秒→1.8秒(71%改善)
• Lighthouseパフォーマンス62点→95点(53%向上)
• 画像合計約8MB→約1.2MB(85%削減)
• LCP 4.8秒→1.2秒(75%改善)

最適化後、ファーストビューは6.2秒→1.8秒、Lighthouseは62→95、直帰率は約35%低下。投資対効果は非常に高い。
Astro Imageコンポーネントの使い方は?
Astro Imageコンポーネントの利点:
• 画像フォーマット・サイズ・遅延読み込みを自動最適化
• <img>の代わりに<Image />を使用
• 圧縮・フォーマット変換・レスポンシブ処理を自動化

設定手順:
1) @astrojs/image統合をインストール(npx astro add image を実行)
2) astro.config.mjsでimageServiceを設定(sharpまたはsquooshを選択)
3) Imageコンポーネントを使用:import { Image } from 'astro:assets'; <Image src={image} alt="説明" />

ローカル画像のパス:
• SSRモードではローカル画像はsrc/配下に置き、public/直リンクは最適化されない
• 正しい例:import image from '../assets/photo.jpg'; <Image src={image} alt="正しい使い方" />
• 誤り:public/の画像は最適化されない
画像フォーマットはどう選ぶ?JPEG・PNG・WebP・AVIFの違いは?
フォーマット選択:
• JPEG(写真・複雑な画像向け、互換性最高)
• PNG(アイコン・透明背景向け、ファイルは大きめ)
• WebP(JPEGより30〜50%小さい、モダンブラウザ対応、90%の場面でWebPで十分)
• AVIF(WebPよりさらに20〜30%小さい、最新フォーマット、互換性はやや低い、極限追求ならAVIFフォールバック)

おすすめ:
• 90%の場面はWebP
• 極限追求ならAVIFフォールバック
• 透明度が必要ならWebPまたはPNG
遅延読み込みとCDN高速化はどう設定しますか?
遅延読み込み:
• ファーストビューは1〜2枚だけ即時読み込み、他はすべて遅延
• 初期読み込み量を50%以上削減できる
• loading="lazy"属性、またはImageコンポーネントのloadingプロパティを使用

Cloudflare CDN連携:
• Cloudflare ImagesまたはR2ストレージを利用
• 自動最適化とフォーマット変換を設定
• 世界300以上のエッジで加速、個人利用は無料枠で十分なことが多い
• 実測でレイテンシが大幅に短縮

設定手順:
1) Cloudflare DashboardでImagesまたはR2を有効化
2) imageServiceでCloudflareを指定
3) 画像をCloudflareに配置
4) Cloudflare URLで画像を読み込む
画像最適化で問題が出たときの切り分けは?
トラブルシューティングチェックリスト:
1) importパスが正しいか確認
2) 画像フォーマットが対応しているか確認
3) リモート画像ドメインが許可リストにあるか確認
4) qualityパラメータが妥当か確認
5) Sharpが正しくインストールされているか確認

よくある問題:
• Sharpインストール失敗 → Nodeバージョンを確認し、npm install sharpを実行
• リモート画像の最適化失敗 → ドメイン許可リストを確認
• SSRモード非対応 → outputを'server'または'hybrid'に設定

チェックリスト順に確認すれば、9割はパス・設定・Sharpの問題です。

8分で読めます · 公開日: 2025年12月3日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます