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 秒
最適化後:
- ファーストビュー読み込み: 1.8 秒(約 70% 改善)
- Lighthouse パフォーマンス: 95 点(約 53% 向上)
- 画像合計: 約 1.2MB(約 85% 削減)
- LCP: 1.3 秒(約 73% 改善)
想定以上の効果でした。直帰率は約 35% 低下 し、コンテンツを読み進めるユーザーが明らかに増えました。
Astro はもともとパフォーマンス重視のフレームワークです。画像最適化のせいでその強みを損なうのはもったいない。ここからは、画像最適化を一つずつ進めていきます。
Astro Image コンポーネント完全ガイド
Astro には <Image /> と <Picture /> が組み込まれており、画像最適化専用です。初めて公式ドキュメントを読んだときは、widths・quality・inferSize が何のためかよくわかりませんでした。実際に試してようやく理解できました。
基本:Image と Picture
まず <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): 細かく調整
私は mid か 80 を使うことが多く、見た目の差はほぼなく、ファイルサイズは 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}
/>
読み込みの流れ:
- まず AVIF(最小・最新)
- 非対応なら WebP(次に小さい・互換性良好)
- それでもダメなら JPEG(最大・100% 互換)
モダンブラウザには最良の体験を、古い環境にも破綻しない表示を届けられます。
圧縮率の実測比較
2.5MB の原図で試しました。
| フォーマット | ファイルサイズ | 圧縮率 | 見た目の品質 |
|---|---|---|---|
| 原図(PNG) | 2.5MB | - | オリジナル |
| JPEG(quality=85) | 450KB | 82% | 肉眼ではほぼ差なし |
| WebP(quality=85) | 180KB | 93% | 肉眼ではほぼ差なし |
| AVIF(quality=85) | 120KB | 95% | 肉眼ではほぼ差なし |
同じ見た目でも、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% |
| LCP | 4.8秒 | 1.3秒 | 73% |
| ファーストビュー画像合計 | 8MB | 1.2MB | 85% |
| 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.mjs の image.domains にドメインを追加してください。
3. compile モードはビルド時のみ最適化
adapter: cloudflare({
imageService: 'compile' // ビルド時のみ最適化
})
パッケージ時に一度だけ最適化し、実行時は再処理しません。純静的サイト向けです。
4. 無料枠に注意
| CDN サービス | 無料枠 | 超過料金 |
|---|---|---|
| Cloudflare Image Resizing | 5万回/月 | $5/5万回 |
| Cloudinary | 25 credits/月 | 従量課金 |
| Uploadcare | 3GB 保存 + 3GB 転送 | 従量課金 |
| Cloudflare R2 | 10GB 保存 | $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="正しい使い方" />
トラブルシューティングチェックリスト
問題が出たら、この順で確認してください。
- ✓ import パスは正しいか
- ✓ 画像フォーマットは対応しているか
- ✓ リモート画像のドメインは許可リストにあるか
- ✓ quality は妥当か
- ✓ Sharp は正しくインストールされているか
- ✓ SSR 設定(imageService など)は正しいか
- ✓ ブラウザ Console にエラーはないか
- ✓ Network タブで画像リクエストの状態を確認したか
ここまで来たら、まとめに入りましょう。
まとめ
Astro の画像最適化に 2 日かけて得た知見を、同じ悩みのある方のために書きました。
核心は次の5点です。
- Image コンポーネント:
<img>の代わりに<Image />を使い、圧縮・フォーマット変換・レスポンシブを自動化 - フォーマット: 90% は WebP で十分。極限なら AVIF フォールバック、透明度は WebP か PNG
- 遅延読み込み: ファーストビューは 1〜2 枚だけ即時、他は lazy で初期読み込みを 50% 以上削減
- CDN: Cloudflare なら無料枠で個人ブログは足り、海外アクセスは約 60% 高速化
- トラブルシューティング: チェックリスト順に確認。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: 画像最適化の重要性と目標を理解する
画像最適化の重要性:
• 画像は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: テクニック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: テクニック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〜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: トラブルシューティングとベストプラクティス
トラブルシューティングチェックリスト:
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コンポーネントの使い方は?
• 画像フォーマット・サイズ・遅延読み込みを自動最適化
• <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日
Astro 完全ガイド
検索からこのページに来た場合は、前後の記事もあわせて読むと同じテーマの理解がかなり早く深まります。
前の記事
Astro ビルド失敗?5 分で切り分ける 7 つのよくある原因
Astro のビルドが失敗して原因がわからない?よくある 7 つのエラーシナリオと、体系的な 5 ステップの切り分け法・具体的な解決策をまとめました。問題の 90% は 5〜10 分で解決できます。
第 14 / 18 記事
次の記事
Astro ブログに Pagefind 検索を追加:無料・高速・日本語対応の完全ガイド
Astro ブログに Pagefind を使って無料かつ高速な全文検索を追加する手順を解説します。日本語対応、インデックスは 100KB 未満、10 分で設定完了。Algolia よりコストも運用もラクです。
第 16 / 18 記事
関連記事
Astro とは?3 分でわかるゼロ JS・アイランドアーキテクチャ・コンテンツ優先の本当の意味
Astro とは?3 分でわかるゼロ JS・アイランドアーキテクチャ・コンテンツ優先の本当の意味
ゼロから Astro ブログを構築:1 時間でトップページからデプロイまで
ゼロから Astro ブログを構築:1 時間でトップページからデプロイまで
Astro Content Collections 完全ガイド:概念から Schema 検証の実践まで
コメント
GitHubアカウントでログインしてコメントできます