Documentation Astro

Astro は静的サイト生成に優れたフレームワークで、特にパフォーマンスを重視した最適化機能が特徴です。その中でも ImagePicture コンポーネントは、画像の最適化とレスポンシブ対応に不可欠なツールです。このガイドでは、両コンポーネントの使用法、パフォーマンス、SEO への影響、そしてそれぞれの詳細な使い分けについて説明します。

この記事で学べること

  • Image と Picture コンポーネントの基本的な使い方
  • ローカル画像とリモート画像の取り扱い
  • レスポンシブ画像の実装方法
  • パフォーマンスとSEOを考慮した最適化手法
  • 両コンポーネントの使い分け

共通点と基礎

インポート方法

両コンポーネントは astro:assets パッケージからインポートされ、画像の最適化と管理を行います。

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

Astro の標準機能として提供されているため、セットアップはシンプルで、プロジェクトにインストールする追加のライブラリは必要ありません。

主要な目的

両コンポーネントの主な目的は以下の通りです。

目的説明
画像の最適化ファイルサイズの縮小により、ページの読み込み時間を短縮
レスポンシブ画像の提供異なる画面サイズに応じて適切な画像を提供
遅延読み込みのサポートlazy ロードにより、ページの表示速度を最適化
CLS の軽減width/height の自動設定でレイアウトシフトを防止

主要な属性

どちらのコンポーネントも以下のような共通の属性を使用します。

属性説明必須
src画像のソース(ローカルまたはリモートURL)
alt画像の代替テキスト(アクセシビリティ用)
width画像の幅(リモート画像では必須)
height画像の高さ(リモート画像では必須)
loading読み込みタイミング("lazy" または "eager"-
decodingデコード方法("async", "sync", "auto"-

Image コンポーネント

基本的な使用方法

Image コンポーネントは、単一の最適化された画像を提供するシンプルなコンポーネントです。

---
import { Image } from 'astro:assets';
import myImage from '../assets/hero.png';
---

<Image src={myImage} alt="ヒーロー画像" />

特徴

  • 自動サイズ設定: ローカル画像の場合、Astro はビルド時に widthheight を自動的に設定します。つまり、ローカルファイルを参照するときにはwidthheightの設定は不要となります。ただし、ローカルでもpublic内の画像は対象とならないので注意しましょう。
  • フォーマット変換: 必要に応じて画像フォーマットを自動的に変換します。
  • 単一の画像提供: このコンポーネントは、単一の最適化された画像を生成し、出力します。

最適化オプション

Image コンポーネントにはフォーマットや画質を指定するオプションがあります。

オプション説明値の例
format出力フォーマット"webp", "avif", "png", "jpeg"
quality出力品質(0-100)80
densitiesピクセル密度の配列[1, 2]

ローカル画像の使用例

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

<!-- 基本的な使用 -->
<Image src={heroImage} alt="ヒーロー画像" />

<!-- フォーマットと品質を指定 -->
<Image
  src={heroImage}
  alt="最適化されたヒーロー画像"
  format="webp"
  quality={80}
/>

<!-- Retinaディスプレイ対応 -->
<Image
  src={heroImage}
  alt="高解像度対応画像"
  densities={[1, 2]}
/>

リモート画像の使用例

リモート画像を使用する場合は、widthheight を必ず指定する必要があります。

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

<Image
  src="https://example.com/image.jpg"
  alt="リモート画像"
  width={800}
  height={600}
  format="webp"
/>

リモート画像の許可設定

リモート画像を使用するには、astro.config.mjs で許可するドメインを設定します。

// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  image: {
    domains: ['example.com', 'images.unsplash.com'],
    // または、すべてのリモート画像を許可
    // remotePatterns: [{ protocol: 'https' }],
  },
});

適用範囲と制約

単一の画像を使用する場合に最適で、特に複雑なレスポンシブ対応やフォーマット切り替えの必要がない場合に向いています。フォーマット指定をしない場合は、Astro が最適な形式で画像を生成しますが、特定のニーズがある場合は手動で設定する必要があります。

Picture コンポーネント

基本的な使用方法

Picture コンポーネントは、複数の画像フォーマットや解像度を提供し、レスポンシブ対応を可能にします。

---
import { Picture } from 'astro:assets';
import myImage from '../assets/hero.png';
---

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

特徴

特徴説明
複数のフォーマットWebP、AVIF、JPEG などを同時に生成し、ブラウザが最適なものを選択
複数の解像度デバイスや画面サイズに応じて異なる解像度の画像を提供
アートディレクションデバイスに応じて異なる画像(トリミング違いなど)を提供可能

追加の属性

属性説明
widths生成する画像幅の配列[400, 800, 1200]
sizesレスポンシブサイズ指定"(max-width: 800px) 100vw, 800px"
formats出力フォーマットの配列['avif', 'webp', 'jpeg']
fallbackFormatフォールバック用フォーマット"jpeg"

使用例:複数フォーマットと解像度

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

<Picture
  src={heroImage}
  alt="レスポンシブ画像"
  widths={[400, 800, 1200, 1600]}
  sizes="(max-width: 640px) 100vw, (max-width: 1024px) 80vw, 1200px"
  formats={['avif', 'webp', 'jpeg']}
/>

この例では、以下が生成されます:

  • 4つの解像度(400px, 800px, 1200px, 1600px)
  • 3つのフォーマット(AVIF, WebP, JPEG)
  • 合計12枚の最適化された画像

アートディレクションとメディアクエリ

Picture コンポーネントは、アートディレクションにも利用できます。以下の例では、特定の画面サイズに応じて異なる画像が表示されます。

---
import { Picture } from 'astro:assets';
import desktopImage from '../assets/hero-desktop.jpg';
import mobileImage from '../assets/hero-mobile.jpg';
---

<Picture
  src={desktopImage}
  alt="レスポンシブ画像"
  widths={[800, 1200, 1600]}
  sizes="(max-width: 800px) 100vw, 800px"
  formats={['avif', 'webp', 'jpeg']}
>
  <source
    media="(max-width: 640px)"
    srcset={mobileImage.src}
  />
</Picture>

このアプローチにより、モバイルユーザーには小さな画像、デスクトップユーザーには大きな画像が提供されます。

適用範囲と制約

複数の解像度やフォーマットを使いたい場合に最適です。フォーマットや解像度が多くなるほど、ビルド時間とストレージ使用量が増加します。

主な違い

生成される HTML

Image コンポーネント

<img
  src="/_astro/hero.abc123.webp"
  alt="説明"
  width="800"
  height="600"
  loading="lazy"
  decoding="async"
/>

Picture コンポーネント

<picture>
  <source type="image/avif" srcset="/_astro/hero.400.avif 400w, /_astro/hero.800.avif 800w" sizes="..." />
  <source type="image/webp" srcset="/_astro/hero.400.webp 400w, /_astro/hero.800.webp 800w" sizes="..." />
  <img src="/_astro/hero.800.jpeg" alt="説明" width="800" height="600" loading="lazy" decoding="async" />
</picture>

比較表

項目ImagePicture
生成されるタグ<img><picture> + <source> + <img>
フォーマット単一複数対応
解像度単一(densities対応可)複数対応
アートディレクション非対応対応
ビルド時間短い長くなる可能性
使用シナリオシンプルな画像表示高度なレスポンシブ対応

使い分けガイド

画像を表示したい

    ├─ 複数のフォーマットが必要?
    │   ├─ Yes → Picture
    │   └─ No ─┐
    │          │
    ├─ 複数の解像度が必要?
    │   ├─ Yes → Picture
    │   └─ No ─┐
    │          │
    ├─ アートディレクションが必要?
    │   ├─ Yes → Picture
    │   └─ No → Image

実践的なコード例

ブログカードの画像

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

interface Props {
  title: string;
  image: ImageMetadata;
  href: string;
}

const { title, image, href } = Astro.props;
---

<article class="blog-card">
  <a href={href}>
    <Image
      src={image}
      alt={title}
      width={400}
      height={225}
      format="webp"
      quality={80}
      class="card-image"
    />
    <h3>{title}</h3>
  </a>
</article>

<style>
  .blog-card {
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }

  .card-image {
    width: 100%;
    height: auto;
    object-fit: cover;
  }
</style>

ヒーローセクションの背景画像

---
import { Picture } from 'astro:assets';
import heroDesktop from '../assets/hero-desktop.jpg';
import heroMobile from '../assets/hero-mobile.jpg';
---

<section class="hero">
  <Picture
    src={heroDesktop}
    alt=""
    widths={[640, 1024, 1440, 1920]}
    sizes="100vw"
    formats={['avif', 'webp', 'jpeg']}
    class="hero-image"
  >
    <source
      media="(max-width: 768px)"
      srcset={heroMobile.src}
    />
  </Picture>
  <div class="hero-content">
    <h1>Welcome to Our Site</h1>
    <p>素晴らしい体験をお届けします</p>
  </div>
</section>

<style>
  .hero {
    position: relative;
    height: 80vh;
    overflow: hidden;
  }

  .hero-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .hero-content {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100%;
    color: white;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  }
</style>

画像ギャラリー

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

// 画像をまとめてインポート
const images = await Astro.glob('../assets/gallery/*.{jpg,png,webp}');
---

<div class="gallery">
  {images.map((image, index) => (
    <figure class="gallery-item">
      <Image
        src={image.default}
        alt={`ギャラリー画像 ${index + 1}`}
        width={300}
        height={300}
        format="webp"
        quality={75}
        class="gallery-image"
      />
    </figure>
  ))}
</div>

<style>
  .gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1rem;
  }

  .gallery-item {
    margin: 0;
    overflow: hidden;
    border-radius: 8px;
  }

  .gallery-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.3s ease;
  }

  .gallery-image:hover {
    transform: scale(1.05);
  }
</style>

パフォーマンスと SEO への影響

画像最適化

両コンポーネントは画像を最適化し、ファイルサイズを削減することで、ページ読み込み速度を向上させます。最適化された画像は、より速く読み込まれるため、ユーザー体験が向上します。

Cumulative Layout Shift (CLS)の軽減

widthheight を指定することで、ページ読み込み時に画像の位置が確保され、レイアウトが崩れることを防ぎます。これにより、CLS が軽減され、GoogleCore Web Vitals において良好な評価を得ることができます。

遅延読み込み

loading="lazy" を指定することで、画面外にある画像を遅延して読み込むことができ、初期読み込みのパフォーマンスが向上します。

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

<!-- それ以外は遅延読み込み(デフォルト) -->
<Image src={contentImage} alt="コンテンツ" loading="lazy" />

画像の発見可能性

SEO の観点から、適切な alt テキストを設定することで、検索エンジンが画像を理解しやすくなり、画像検索のランキングが向上します。

画像フォーマットの影響

次世代フォーマット(WebPAVIF)を使用することで、画像サイズがさらに圧縮され、パフォーマンスが向上します。

フォーマット圧縮率ブラウザ対応用途
AVIF最高新しいブラウザ最新環境向け
WebPほぼ全ブラウザ汎用
JPEG全ブラウザフォールバック
PNG全ブラウザ透過が必要な場合

ベストプラクティス

適切な alt テキスト

常に意味のある代替テキストを設定しましょう。これにより、アクセシビリティが向上し、SEO も改善されます。

<!-- 良い例 -->
<Image src={productImage} alt="赤いレザーのハンドバッグ、正面から撮影" />

<!-- 悪い例 -->
<Image src={productImage} alt="画像" />
<Image src={productImage} alt="product-image-001.jpg" />

<!-- 装飾的な画像の場合は空に -->
<Image src={decorativeImage} alt="" />

サイズ最適化

表示サイズに適した widthheight を指定し、レイアウトシフトを防ぎます。

<!-- 表示サイズに合わせた指定 -->
<Image
  src={thumbnailImage}
  alt="サムネイル"
  width={150}
  height={150}
/>

<!-- アスペクト比を維持してリサイズ -->
<Image
  src={largeImage}
  alt="リサイズ画像"
  width={800}
  height={Math.round(800 * (largeImage.height / largeImage.width))}
/>

フォーマット選択

次世代フォーマット(AVIFWebP)を使用し、画像サイズを最小化しましょう。Picture コンポーネントでは、複数のフォーマットを提供することで、すべてのブラウザに対応することができます。

パフォーマンスを考慮した読み込み

重要でない画像には loading="lazy" を使用し、初期ページロードの速度を向上させましょう。

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

<!-- LCP(Largest Contentful Paint)対象の画像 -->
<Image
  src={heroImage}
  alt="メインビジュアル"
  loading="eager"
  fetchpriority="high"
/>

<!-- スクロール後に表示される画像 -->
<Image
  src={contentImage}
  alt="コンテンツ画像"
  loading="lazy"
/>

注意点

ビルド時間

大量の画像や複数のフォーマットを生成する場合、ビルド時間が増加する可能性があります。

対策:

  • Picture の使用は本当に必要な箇所に限定
  • 生成する widths の数を必要最小限に
  • 開発時はキャッシュを活用

ストレージ使用量

複数のサイズやフォーマットの画像を生成すると、プロジェクトのストレージ使用量が増加します。

対策:

  • フォーマットは2〜3種類に絞る(例:AVIF, WebP, JPEG)
  • 解像度は実際に必要なサイズのみ指定

ブラウザ互換性

古いブラウザでは、次世代フォーマット(WebPAVIF)をサポートしていない場合があります。

対策:

  • Picture コンポーネントでフォールバック用の JPEG/PNG を含める
  • formats 配列の最後に互換性の高いフォーマットを指定
<Picture
  src={image}
  alt="互換性を考慮した画像"
  formats={['avif', 'webp', 'jpeg']} <!-- jpegがフォールバック -->
/>

まとめ

このガイドでは、AstroImage および Picture コンポーネントの詳細な使用方法、パフォーマンス向上、SEO への影響、適切な実装方法について解説しました。

ポイントの振り返り

  • Image: シンプルな画像表示に最適。単一フォーマット・解像度
  • Picture: 高度なレスポンシブ対応に最適。複数フォーマット・解像度・アートディレクション
  • パフォーマンス: 次世代フォーマット + 遅延読み込みで最適化
  • SEO: 適切な alt テキストと width/height の指定が重要
  • 注意点: ビルド時間とストレージ使用量のバランスを考慮

これらのコンポーネントを適切に活用することで、ウェブサイトのパフォーマンスを最大限に引き出し、ユーザー体験を向上させることができます。

参考文献

円