TOSAKAFUNK

Loading...

まだタグ? Next.js開発者が知るべきnext/imageの恩恵。WebP変換と画像パスの使い分けを理解する

まだタグ? Next.js開発者が知るべきnext/imageの恩恵。WebP変換と画像パスの使い分けを理解する のビジュアル

Next.jsのnext/imageは画像最適化をどこまで自動化できるのでしょうか?
本記事では、WebP自動変換やリサイズといった具体的な恩恵から、開発者が混乱しがちなpublicとsrc/assetsの使い分け基準までを徹底解説。
next/imageを正しく理解し、パフォーマンス改善を自動化する第一歩を踏み出しましょう。

  • 自動最適化next/imageはWebPなど次世代フォーマットへの自動変換、デバイス毎のリサイズ、遅延読み込み(Lazy Loading)を標準で提供します。
  • src vs publicsrc(assets)からのインポートはビルド時の最適化とハッシュ付与に、publicはCMSなど外部管理画像や静的アセット(favicon除く)に適しています。
  • 静的インポートの利点src内の画像をimportすると、画像の存在チェックやwidth/heightの自動設定、強力なキャッシュ(ハッシュ)の恩恵を受けられます。
  • 導入効果LCP(Largest Contentful Paint)の劇的な改善、Core Web Vitalsのスコア向上、開発工数の削減に直結します。

<img>タグのまま? Next.js開発者が抱える画像最適化の「面倒くさい」問題

Next.jsでの開発中、画像の扱いに悩んでいませんか? パフォーマンスの重要性は理解しつつも、従来の`<img>`タグをそのまま使ってしまっているケースは少なくありません。

Next.jsには強力な画像最適化コンポーネントである`next/image`が用意されていますが、その導入にはいくつかの心理的ハードルが存在します。

「とりあえず<img>」が引き起こすパフォーマンスの懸念

<img>タグをそのまま使用すると、以下のような問題が発生しがちです。

  • 巨大な生画像の読み込みによる、ページの表示速度(特にLCP)の悪化。
  • ブラウザがサポートしているにもかかわらず、WebPなどの次世代フォーマットを提供できない。
  • レスポンシブ対応のために、手動で複数の画像サイズ(srcset)を管理する必要がある。
  • 画像の読み込み遅延(Lazy Loading)を自前で実装する必要がある。

これらの問題は、Core Web Vitalsのスコアに直接影響し、結果としてユーザー体験(UX)やSEO評価の低下につながる可能性があります。

next/imageへの移行を妨げる「3つの誤解」

多くの開発者が`next/image`の利用をためらう背景には、以下のような誤解や疑問があります。

  1. 「設定が面倒そう」: next.config.jsの記述や、多くの`props`(プロパティ)を覚えるのが大変だと感じてしまう。
  2. 「画像の置き場所が分からない」: publicディレクトリに置くべきか、src/assetsなどからimportすべきか、明確な基準が分からない。
  3. 「自動化の範囲が不明確」: 「どこまで自動でやってくれるのか?」が具体的に分からず、導入メリットを確信できない。

本記事では、これらの疑問を解消し、next/imageがいかに強力で、かつ簡単に開発者の負担を軽減してくれるかを解説します。


手動での画像最適化が招く「工数」と「UX低下」という悪循環

next/imageを使わずに手動で画像最適化を行おうとすると、開発プロセスは一気に複雑化します。

Core Web Vitals(特にLCP)への深刻な影響

LCP (Largest Contentful Paint) は、ビューポート内で最も大きなコンテンツ(多くの場合、画像や動画)が読み込まれる速度を示す指標です。<img>タグで巨大な画像をそのまま配信すると、LCPの値は著しく悪化します。

また、画像のサイズ(width, height)が指定されていないと、画像読み込み後にレイアウトがガタつくCLS (Cumulative Layout Shift) が発生し、ユーザーにストレスを与えてしまいます。

Core Web Vitalsは、Googleが提唱するUXの質を測定するための核となる指標群です。LCP、CLS、FID(INP)が含まれ、これらは検索順位にも影響を与える要因とされています。

デバイスごとに画像を用意する非効率な運用

スマートフォン、タブレット、PCなど、異なるデバイス解像度(ビューポート)に対応するため、<img>タグのsrcset属性を手動で管理することを想像してみてください。

  • デザインカンプから画像を書き出す。
  • @1x, @2x, @3x… または 320w, 640w, 1024w… など、複数の解像度を手動で(またはスクリプトで)生成する。
  • それらをすべてリポジトリにコミットし、`srcset`に記述する。

この作業は非常に手間がかかるだけでなく、画像の差し替えが発生するたびに同様の作業が必要となり、メンテナンスコストが膨れ上がります。


解決策はnext/image! 驚くべき「画像最適化の自動化」機能

next/imageコンポーネントは、これらの問題を「自動的」に解決するために設計されています。開発者は、最適化のロジックを意識することなく、コンポーネントを使うだけでその恩恵を受けられます。

1. 次世代フォーマット(WebP/AVIF)への自動変換

開発者が用意する元画像がJPEGやPNGであっても、next/imageはブラウザのサポート状況(Acceptヘッダー)に応じて、自動的にWebPやAVIFといった次世代フォーマットに変換して配信します。

これにより、画質を維持したままファイルサイズを大幅に削減(一般的にJPEGより25〜35%削減)でき、読み込み速度が向上します。

2. デバイスサイズに応じた自動リサイズ(`srcset`の動的生成)

手動での`srcset`管理は不要です。`next/image`は、デバイスのビューポートや`sizes`プロパティに基づき、必要な画像サイズをオンデマンドで自動生成し、適切な`srcset`をHTMLに出力します。

開発者は基本的に1つの高解像度な元画像を用意するだけで、あとはNext.jsが最適な画像を配信してくれます。

3. ビューポート外画像の自動遅延読み込み(Lazy Loading)

デフォルトで、next/image遅延読み込み(loading=”lazy”)が有効になっています。これは、画像がビューポート(画面表示領域)に近づくまで読み込みを開始しない技術です。

ページの初期読み込み速度(First Contentful Paint)を高速化し、不要なデータ通信を削減できます。(※LCPになる可能性のある画像には priority={true} を指定することが推奨されます)

4. CLS(レイアウトシフト)の自動防止

next/imageは、widthheightプロパティを必須(または`fill`プロパティの使用)とすることで、画像の表示領域を事前に確保します。これにより、画像読み込みによるレイアウトのガタつき(CLS)を自動的に防ぎます。


開発者の疑問に答える! publicとsrc/assetsの明確な使い分け基準

next/imageの利点は分かりましたが、最も混乱しやすいのが「画像をどこに置くか」です。publicディレクトリとsrc(またはapp)ディレクトリ内のassetsフォルダ、どちらを使うべきでしょうか。

結論:原則としてsrc(assets)からの「静的インポート」を推奨

アプリケーションのコンポーネント内で使用するロゴ、アイコン、記事のサムネイルなど、ビルド時に存在が確定している画像は、src/assets(またはapp/assetsなど)のディレクトリに配置し、importして使用することを強く推奨します。

src/app/page.tsx で静的インポートする例:

import Image from 'next/image';
import profileImage from '@/assets/images/profile.png'; // (1) src/assetsから画像をimport

export default function Home() {
  return (
    <main>
      <h1>My Profile</h1>
      {/* (2) importした変数を src プロパティに渡す */}
      <Image
        src={profileImage}
        alt="プロフィール画像"
        placeholder="blur" // オプション: ブラーアップ効果
      />
    </main>
  );
}

静的インポートがもたらす3大メリット

1. ビルド時の存在チェック

画像ファイルが存在しない場合、`import`時にエラーが発生するため、リンク切れの画像をデプロイしてしまうミスを防げます。

2. widthと`height`の自動設定

静的にインポートされた画像(`.jpg`, .png, .webpなど)は、Next.jsが自動的に`width`と`height`を検出し、コンポーネントに設定します。開発者が手動で指定する必要がありません。

3. 強力なキャッシュ(コンテンツハッシュ)

インポートされた画像は、ビルド時にコンテンツハッシュ(例: _next/image?url=%2F_next%2Fstatic%2Fmedia%2Fprofile.a1b2c3d4.png…)が付与されます。画像が更新されない限りURLが変わらないため、ブラウザやCDNで強力にキャッシュされます。

ではpublicディレクトリはいつ使うのか?

publicディレクトリは、Next.jsのビルドプロセスから「除外」され、そのままルート(`/`)に配置されるファイル群です。`next/image`で`public`内の画像を使う場合、パスは文字列(例: /images/hero.jpg)で指定します。

publicが適しているケース

  • favicon.icoやrobots.txt, sitemap.xml: これらは`src`からのインポート対象外であり、publicに配置する必要があります。
  • CMSや外部DBからパスが提供される画像: ビルド時に存在が確定できない、動的に変わる画像パス(例: /uploads/image.jpg)を参照する場合。ただし、このケースでは`src`に文字列を渡すため、`width`と`height`を手動で指定する必要があります。
  • (非推奨)静的インポートのメリットが不要な、ごく一部の静的アセット。

外部ドメイン画像の最適化と設定(next.config.js)

CMSや画像配信サービス(例: microCMS, Cloudinary)など、外部ドメインにある画像も`next/image`で最適化できます。ただし、セキュリティのため、許可するドメインをnext.config.js(またはnext.config.mjs)に明示的に設定する必要があります。

next.config.mjs で外部ドメインを許可する例:

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.microcms-assets.io',
        port: '',
        pathname: '/assets/**',
      },
    ],
  },
};

export default nextConfig;

この設定により、指定したドメインの画像もNext.jsの画像最適化サーバーを経由し、WebP変換やリサイズの恩恵を受けられるようになります。


next/imageで実現する未来:開発体験(DX)とユーザー体験(UX)の同時向上

next/imageは、単なる<img>タグの代替ではありません。画像最適化という複雑で面倒なタスクをフレームワークレベルで自動化し、開発者(DX)とユーザー(UX)の両方に大きなメリットをもたらす強力な機能です。

まずは1枚の画像から`next/image`に置き換えてみよう

これまで<img>タグを使っていた箇所を、まずは1つでも`next/image`に置き換えてみてください。特に、`src`からの静的インポートを試すことで、width/height指定の手間がなくなる快適さと、Lighthouseスコアの改善をすぐに体感できるはずです。

publicと`src`の使い分けをマスターし、Next.jsのポテンシャルを最大限に引き出しましょう。