Next.js画像最適化(next/image)の基本

2025-08-14

はじめに

現代のWeb開発において、画像最適化はパフォーマンス向上の重要な要素です。Next.jsが提供するnext/imageコンポーネントを使えば、簡単に最適化された画像を表示できます。この記事では、next/imageの基本的な使い方から実践的な応用まで、初心者の方にもわかりやすく解説します。

なぜnext/imageが必要なのか?

従来の<img>タグには以下の課題があります:

  1. パフォーマンス問題:適切なサイズでない画像が読み込まれる
  2. SEOへの影響:遅い読み込みがページスコアを下げる
  3. レスポンシブ対応:デバイスごとに適切な画像を手動で設定する必要がある
  4. フォーマット最適化:最新の画像フォーマット(WebPなど)への自動変換ができない

next/imageはこれらの問題を解決し、以下の機能を提供します:

  • 自動的な画像最適化
  • レスポンシブイメージ(デバイスに合わせたサイズ調整)
  • 遅延読み込み(Lazy Loading)
  • プレースホルダーのサポート
  • 自動的なWebP変換(ブラウザがサポートしている場合)
  • 画像のサイズ自動リサイズ

next/imageの基本使用法

1. 基本的なインポートと使用

まず、next/imageからImageコンポーネントをインポートします。

import Image from 'next/image';

function MyComponent() {
  return (
    <div>
      <Image
        src="/images/profile.jpg"
        alt="プロフィール画像"
        width={500}
        height={300}
      />
    </div>
  );
}

必須プロパティ

  • src: 画像のパス(必須)
  • alt: 代替テキスト(必須、アクセシビリティ向上)
  • width: 画像の表示幅(必須、px単位)
  • height: 画像の表示高さ(必須、px単位)

画像のソース指定方法

1. ローカル画像(publicディレクトリ内)

<Image
  src="/images/hero.jpg" // publicディレクトリからの相対パス
  alt="ヒーローイメージ"
  width={1200}
  height={800}
/>

2. 外部URLの画像

<Image
  src="https://example.com/images/product.jpg"
  alt="製品画像"
  width={600}
  height={400}
  // 外部画像を使用する場合はnext.config.jsの設定が必要
/>

next.config.jsで許可するドメインを設定:

module.exports = {
  images: {
    domains: ['example.com'],
  },
};

画像最適化の主要機能

1. レスポンシブ画像

layoutプロパティでレスポンシブ対応を簡単に実装:

<Image
  src="/images/banner.jpg"
  alt="バナー画像"
  layout="responsive"
  width={1200}
  height={600}
/>

2. 遅延読み込み(Lazy Loading)

<Image
  src="/images/gallery.jpg"
  alt="ギャラリー画像"
  width={800}
  height={600}
  loading="lazy" // ビューポートに近づいたら読み込み
/>

3. プレースホルダー

画像読み込み中のプレースホルダーを設定:

<Image
  src="/images/featured.jpg"
  alt="特集画像"
  width={800}
  height={600}
  placeholder="blur" // ぼかし効果
  blurDataURL="data:image/png;base64,..." // 低解像度プレースホルダー
/>

4. 品質設定

<Image
  src="/images/high-quality.jpg"
  alt="高品質画像"
  width={1000}
  height={500}
  quality={85} // 85%品質(デフォルト75)
/>

レイアウトモードの選択

layoutプロパティで画像のレンダリング方法を制御できます:

1. intrinsic(デフォルト)

  • 画像を元のサイズ以下に縮小
  • 親要素より大きくなることはない
<Image
  src="/images/photo.jpg"
  alt="写真"
  width={1000}
  height={600}
  layout="intrinsic"
/>

2. fixed

  • 指定したwidth/heightで固定表示
  • レスポンシブ対応しない
<Image
  src="/images/icon.png"
  alt="アイコン"
  width={100}
  height={100}
  layout="fixed"
/>

3. responsive

  • 親要素に合わせて拡大縮小
  • 画面幅に応じて最適なサイズを表示
<Image
  src="/images/banner.jpg"
  alt="バナー"
  width={1200}
  height={400}
  layout="responsive"
/>

4. fill

  • 親要素いっぱいに表示
  • objectFitプロパティと組み合わせて使用
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/images/background.jpg"
    alt="背景画像"
    layout="fill"
    objectFit="cover" // "contain", "fill"など
  />
</div>

実践的な使用例

1. 商品ギャラリー

import Image from 'next/image';

function ProductGallery({ products }) {
  return (
    <div className="gallery">
      {products.map((product) => (
        <div key={product.id} className="product-card">
          <div className="image-container">
            <Image
              src={product.imageUrl}
              alt={product.name}
              width={300}
              height={300}
              layout="responsive"
              placeholder="blur"
              blurDataURL={product.thumbnailUrl}
            />
          </div>
          <h3>{product.name}</h3>
          <p>{product.price}円</p>
        </div>
      ))}
    </div>
  );
}

2. ヒーローイメージ

import Image from 'next/image';

function HeroSection() {
  return (
    <section className="hero">
      <div className="hero-image">
        <Image
          src="/images/hero-large.jpg"
          alt="会社のビジョン"
          layout="fill"
          objectFit="cover"
          quality={90}
          priority // 優先的に読み込む
        />
      </div>
      <div className="hero-content">
        <h1>次世代のテクノロジー</h1>
        <p>未来を創造するソリューション</p>
      </div>
    </section>
  );
}

// CSS例
.hero {
  position: relative;
  height: 80vh;
}

.hero-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.hero-content {
  position: relative;
  z-index: 1;
  color: white;
  text-align: center;
  padding-top: 20vh;
}

パフォーマンス最適化のヒント

1. priority属性で重要画像を優先読み込み

<Image
  src="/images/above-the-fold.jpg"
  alt="最初に表示される重要な画像"
  width={1200}
  height={630}
  priority // LCP(Largest Contentful Paint)要素に使用
/>

2. 適切なサイズ指定

// 実際に表示されるサイズに近い値を指定
<Image
  src="/images/content.jpg"
  alt="コンテンツ画像"
  width={800}  // 実際の表示幅
  height={450} // 実際の表示高さ
/>

3. 画像フォーマットの最適化

Next.jsは自動的にWebPに変換しますが、元画像も最適な形式で用意しましょう:

  • 写真: JPEG
  • ロゴ・アイコン: PNGまたはSVG
  • アニメーション: GIF(ただし動画の方が効率的な場合も)

よくある問題と解決方法

1. 画像が歪んで表示される

原因: width/heightのアスペクト比が元画像と異なる
解決策:

// 正しいアスペクト比を維持
<Image
  src="/images/product.jpg"
  alt="製品画像"
  width={800}
  height={800} // 正方形の場合
  layout="responsive"
/>

2. 外部画像が表示されない

原因: ドメインが許可されていない
解決策: next.config.jsにドメインを追加

module.exports = {
  images: {
    domains: ['example.com', 'cdn.shopify.com'],
  },
};

3. 画像がぼやける

原因: 低品質設定または不適切なサイズ
解決策:

<Image
  src="/images/high-res.jpg"
  alt="高解像度画像"
  width={1200}
  height={800}
  quality={85} // 品質向上
  placeholder="blur" // 読み込み中のぼかしを追加
/>

next/imageの高度な設定

1. カスタムローダーの使用

next.config.jsでカスタム画像ローダーを設定できます:

module.exports = {
  images: {
    loader: 'custom',
    path: 'https://example.com/images/',
  },
};

2. デバイスごとに異なる画像を表示

deviceSizesでブレークポイントを設定:

module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
};

まとめ

Next.jsのnext/imageコンポーネントについて学びました。主なポイントは:

  1. next/imageは画像最適化を自動化する強力なコンポーネント
  2. レスポンシブ対応、遅延読み込み、フォーマット変換を簡単に実装
  3. layoutプロパティで様々な表示方法を選択可能
  4. パフォーマンス向上のためにpriorityqualityを適切に設定
  5. 外部画像を使用する場合はnext.config.jsの設定が必要

next/imageを使用することで、画像関連のパフォーマンス問題を大幅に改善できます。ただし、複雑な画像処理が必要な場合や、既存のCDNソリューションを使用している場合は、カスタム設定が必要になることもあります。

次回はNext.jsのAPIルート機能について解説します。フロントエンドと同じプロジェクト内でAPIエンドポイントを作成できる、非常に便利な機能です。

Next.js公式ドキュメントも参考にしてください:
https://nextjs.org/docs/api-reference/next/image