参考サイト
Next.js 13のImageコンポーネントの簡単な使い方とメリット
https://www.zenryoku-kun.com/post/nextjs13-image
画像最適化の舞台裏をのぞき見👀してnext/imageを使いこなす
https://zenn.dev/reiwatravel/articles/fb1586ea9463a1
Next.js の Image コンポーネントの使い方をまとめてみた
https://dev.classmethod.jp/articles/next-js-image-component/
Next.jsのImageコンポーネントとは?
Imageコンポーネントは、HTMLのimgタグをラップしたコンポーネントです。
HTMLのimgタグよりもNext.jsが用意したImageコンポーネントを使用することが推奨
画像最適化
デバイスに合わせてサイズ調整、フォーマット変換、圧縮が行われます
→ファイルサイズの削減、読み込み時間の短縮
srcsetはどうする?(例)デザイナーから画像を2種(等倍1x、2倍2x)を渡されたら
下記の通りデザイナーが表示速度を考慮して1x用にWebPを、高解像度デバイス用に品質重視でPNGを用意したというケースです。
<img
srcset="/example-400.webp 1x,
/example-800.png 2x"
src="/example-400.webp"
/>
Next.jsのImageコンポーネントの場合
<Image
src="/example-800.png" // 2x解像度の画像
alt="画像の説明文"
width={400} // 1xでの表示サイズ
height={300} // 1xでの表示サイズ
/>
Next.jsのImageは、上記の通りサイズの大きい画像だけの使用で下記の最適化
- WebPへの自動変換
- 解像度の最適化
画像の表示領域をロードされる前から確保
画像の表示領域をロードされる前から確保しレイアウトシフトを防止
- Imageコンポーネントの使用:
next/imageからインポートして使用します。- 例:
import Image from 'next/image'
- 自動最適化:
- 画像サイズの最適化
- フォーマットの最適化(WebPなどの最新フォーマットへの変換)
- 遅延読み込み(Lazy Loading)の自動適用
- レスポンシブ対応:
- デバイスのサイズに応じて適切な画像サイズを提供
sizes属性を使用してブレークポイントを指定可能
- ローカル画像の使用:
- インポートした画像ファイルを直接src属性に指定可能
- 幅と高さが自動的に検出される
- リモート画像の使用:
- URL文字列をsrc属性に指定
- width、height属性の指定が必要
- プレースホルダーとブラー効果:
placeholder="blur"を指定することで、ロード中にぼかし効果を適用可能blurDataURL属性でカスタムのプレースホルダー画像を指定可能
- 優先度の設定:
priority属性を使用してLCP(Largest Contentful Paint)要素を指定可能
- カスタマイズ:
next.config.jsで画像の最適化設定をカスタマイズ可能
ローカル画像とリモート画像
ローカル画像
ローカル画像は、プロジェクト内のディレクトリに配置されます。
ビルド時に最適化されます。
import Image from 'next/image'
export default function LocalImageExample() {
return (
<Image
src="/images/example.jpg"
alt="Example image"
width={500}
height={300}
/>
)
}
リモート画像
リモート画像は、外部のサーバーやサービスから動的に取得される画像です。
width、height属性の指定が必要
- CMS(Content Management System)、CDN(Content Delivery Network)、S3などから配信される
- アプリケーションの実行時に取得される
- 画像の更新が容易(アプリケーションの再デプロイなしで更新可能)
import Image from 'next/image'
export default function RemoteImageExample() {
return (
<Image
src="https://example.com/images/remote-image.jpg"
alt="Remote image example"
width={500}
height={300}
/>
)
}
レスポンシブデザインでの使用
Image コンポーネントは、レスポンシブデザインにも対応しています。sizes プロパティを使用することで、異なる画面サイズに対して適切な画像サイズを指定できます。
<Image
src="/example.jpg"
alt="Example"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
fill
/>
背景画像の最適化実装
通常の画像だけでなく背景画像の最適化にも活用できます。
背景画像に Image コンポーネントを使用します。
import Image from 'next/image';
export default function BackgroundImageExample() {
return (
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/background-image.jpg"
alt="背景画像"
fill
style={{ objectFit: 'cover' }}
/>
<div style={{ position: 'relative', zIndex: 1 }}>
{/* ここにコンテンツを配置 */}
<h1>ようこそ</h1>
<p>これは背景画像の上に表示されるコンテンツです。</p>
</div>
</div>
);
}
SSGでの画像最適化
下記については変わらず使用ができます。
- width / height によるレイアウト保持(CLS防止)
- lazy / srcset / sizes の自動付与(軽量化・レスポンシブ対応)
Imageコンポーネントで利用する画像最適化APIは静的エクスポートでは使用できません
そのため、WebP変換やリサイズ最適化などは使用できません
DocsErrorsExport with Image Optimization API
https://nextjs.org/docs/messages/export-image-api
Next.js 16 日本語ドキュメント
https://nextjsjp.org/docs/app/guides/static-exports#%E7%94%BB%E5%83%8F%E6%9C%80%E9%81%A9%E5%8C%96
WebP/PNG の両方を x1・x2(倍密度)対応させたい場合
WebPとPNGの両方で、x1・x2それぞれの画像を適切に切り替えたい場合は、Imageコンポーネントを使わず、下記のように記述するのが適しています。
WebPはすでに9割以上のブラウザで対応しているため、基本的にはWebPのみでも問題ないかと思います
ブラウザ検証画面のコンソール画面でconsole.log(window.devicePixelRatio);で確認できます
→1であれば非Retinaディスプレイで1x画像が表示されます
picture
│
├─ 639px以下(SP)
│ │
│ ├─ WebP対応
│ │ ├─ 高解像度(2x以上) → hero_sp@2x.webp
│ │ └─ 通常解像度(1x) → hero_sp.webp
│ │
│ └─ WebP非対応
│ ├─ 高解像度(2x以上) → hero_sp@2x.png
│ └─ 通常解像度(1x) → hero_sp.png
│
└─ 640px以上(PC)
│
├─ WebP対応
│ ├─ 高解像度(2x以上) → hero_pc@2x.webp
│ └─ 通常解像度(1x) → hero_pc.webp
│
└─ WebP非対応
├─ 高解像度(2x以上) → hero_pc@2x.png
└─ 通常解像度(1x) → hero_pc.png
<picture className={styles.heroImage}>
{/* SP向け - WebP対応ブラウザ */}
<source
media="(max-width: 639px)"
type="image/webp"
srcSet={`${basePath}/img/sample/hero/hero_sp.webp 1x, ${basePath}/img/sample/hero/hero_sp@2x.webp 2x`}
/>
{/* SP向け - 非対応ブラウザ向け(PNGフォールバック) */}
<source
media="(max-width: 639px)"
type="image/png"
srcSet={`${basePath}/img/sample/hero/hero_sp.png 1x, ${basePath}/img/sample/hero/hero_sp@2x.png 2x`}
/>
{/* PC向け - WebP対応ブラウザ */}
<source
media="(min-width: 640px)"
type="image/webp"
srcSet={`${basePath}/img/sample/hero/hero_pc.webp 1x, ${basePath}/img/sample/hero/hero_pc@2x.webp 2x`}
/>
{/* PC向け - 非対応ブラウザ向け(PNGフォールバック) */}
<img
className={styles.heroImage}
src={`${basePath}/img/sample/hero/hero_pc.png`}
srcSet={`${basePath}/img/sample/hero/hero_pc.png 1x, ${basePath}/img/sample/hero/hero_pc@2x.png 2x`}
alt="サンプル画像の説明テキスト"
loading="lazy"
/>
</picture>
