メインコンテンツまでスキップ

画像最適化

Web Almanacによると、画像は一般的なウェブサイトのページウェイトの大部分を占めており、ウェブサイトのLCP パフォーマンスに大きな影響を与える可能性があります。

Next.js Image コンポーネントは、HTML の<img>要素を拡張し、画像を自動的に最適化する機能を備えています:

  • **サイズの最適化:**WebP や AVIF のような最新の画像フォーマットを使用して、各デバイス用に正しいサイズの画像を自動的に提供します
  • **視覚的安定性:**画像の読み込み時に自動的にレイアウトシフトが起こらないようにする
  • **ページ読み込みの高速化:**画像はブラウザネイティブの LazyLoad を使用して、ビューポートに入ったときにのみ読み込まれます。オプションでブラーを入れることもできます
  • **アセットの柔軟性:**リモートサーバーに保存された画像もオンデマンドでリサイズ可能です

🎥 Watch: next/imageの使い方はこちら → YouTube(9 分)

使用方法

import Image from 'next/image'

そして、画像(ローカルまたはリモート)のsrcを定義できます。

ローカルの画像

ローカル画像を使用するには、.jpg.png、または.webp画像ファイルをimportします。

Next.js は、インポートされたファイルに基づいて、画像の幅と高さを自動的に決定します。これらの値は、画像の読み込み中に累積レイアウトシフトの発生を防ぐために使用されます。

app/page.js
import Image from 'next/image'
import profilePic from './me.png'

export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
// width={500} 自動的に提供される
// height={500} 自動的に提供される
// blurDataURL="data:..." 自動的に提供される
// placeholder="blur" // Optional: ローディング中にぼかす
/>
)
}

注意: 動的なawait import()require()はサポートされていません。ビルド時に解析できるように、importは静的に行われている必要があります。

リモートの画像

リモート画像を使用するには、srcプロパティに URL 文字列を指定します。

Next.js はビルドプロセス中にリモートファイルへアクセスできないため、widthheight、およびオプションのblurDataURL属性を指定する必要があります。

widthと  height属性は、画像の正しい縦横比を推測し、画像の読み込みによるレイアウトシフトを避けるために使われます。widthと  heightは、画像ファイルのレンダリングサイズを決定するものではありません。画像のサイズについてはこちらを参照してください。

app/page.js
import Image from 'next/image'

export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}

画像の最適化を安全に許可するには、next.config.jsでサポートする URL パターンのリストを定義します。悪意のある利用を防ぐため、できるだけ具体的に記述してください。例えば、以下の設定は特定の AWS S3 バケット内にある画像のみを許可します:

next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
}

remotePatternsの設定についてはこちらを参照してください。画像のsrcに相対 URL を使いたい場合は、loaderを使用します。

ドメイン

リモート画像を最適化したい場合でも、ビルトインの画像最適化 API を使用したい場合があります。その場合は、loaderをデフォルト設定のままにして、Image のsrc属性に絶対 URL を入力します。

悪意のあるユーザーからアプリケーションを保護するには、next/imageコンポーネントで使用するリモートホスト名のリストを定義する必要があります。

remotePatternsの設定についてはこちらを参照してください

Loaders

先ほどの例では、リモート画像に対して部分的な URL("/me.png")が与えられていることに注意してください。これは loader のアーキテクチャにより可能になっています。

loader は画像の URL を生成する関数です。与えられたsrc  を変更し、異なるサイズの画像をリクエストするための複数の URL を生成します。これらの複数の URL はsrcsetの自動生成に使用され、サイト訪問者のビューポートに適したサイズの画像が提供されます。

Next.js アプリケーションのデフォルトの loader は、ビルトインの画像最適化 API を使用します。この API は、ウェブ上のどこからでも画像を最適化し、Next.js の Web サーバーから直接画像を提供します。CDN や画像サーバーから直接画像を提供したい場合は、数行の JavaScript で独自の loader 関数を書くことができます。

loader属性で、画像ごとに loader を定義することも、loaderFile設定でアプリケーション・レベルでも定義できます。

優先順位

各ページのLCP(Largest Contentful Paint)要素となる画像に、 priorityプロパティを追加するべきです。そうすることで、Next.js が(preload タグや Priority Hints などを通じて)特別に画像を優先的に読み込むようになり、LCP が劇的に向上します。

LCP 要素は通常、ページのビューポート内に表示される最大の画像またはテキスト・ブロックです。next devを実行すると、LCP 要素がpriority属性を持たない<Image>の場合、コンソールに警告が表示されます。

LCP イメージを特定したら、次のように属性を追加します:

app/page.js
import Image from 'next/image'
import profilePic from '../public/me.png'

export default function Page() {
return <Image src={profilePic} alt="Picture of the author" priority />
}

優先順位についての詳細はnext/imageコンポーネントのドキュメントを参照してください。

画像サイズの指定

画像がパフォーマンスを低下させるよくある原因のひとつに、レイアウトシフト があります。このパフォーマンスの問題は、Cumulative Layout Shift(累積レイアウトシフト)と呼ばれる独自の Core Web Vital を持つほど、ユーザーにとって厄介な問題です。画像によるレイアウトシフトを避けるには、画像のサイズを常に指定することです。こうすることで、ブラウザは画像を読み込む前に、その画像に十分なスペースを確保できます。

next/imageは好パフォーマンスを保証するように設計されているため、レイアウトシフトを助長するような使い方はできず、以下のいずれかの方法でサイズを指定する必要があります:

  1. static import を使って自動的に行う
  2. widthheight属性を使って明示的に行う
  3. fillを使って、親要素いっぱいに広げることで暗黙的に行う

画像のサイズがわからない場合は?

サイズがわからない画像にアクセスする必要がある場合、いくつかできることがあります:

fill を使用する

fill属性によって、画像が親要素によってサイズ調整されます。CSS を使用して、画像の親要素にページ上のスペースを与え、メディアクエリのブレークポイントに合うようにsizes属性を指定することを検討してください。また、fillcontaincoverを使ったobject-fitや、object-positionを使って、画像がそのスペースをどのように占めるべきかを定義することもできます。

画像を正規化する

管理しているソースから画像を提供している場合、画像を特定のサイズに正規化するために画像パイプラインを修正することを検討してください。

API コールを修正する

アプリケーションが(CMS などの)API コールを使って画像の URL を取得している場合、URL と一緒に画像の寸法を返すように API コールを修正できるかもしれません。

画像のサイズを調整するために、どの方法もうまくいかない場合、next/imageコンポーネントは、標準的な<img>要素と並んでページ上でうまく機能するように設計されています。

スタイリング

Image コンポーネントのスタイリングは、通常の<img>要素のスタイリングと似ていますが、いくつか注意すべきガイドラインがあります:

  • styled-jsxではなくclassNameまたはstyleを使用する
    • ほとんどの場合、classNameを使用することをお勧めします。これは、インポートされたCSS モジュールグローバル・スタイルシートです
    • またstyle属性を使ってインラインスタイルを割り当てることもできます
    • styled-jsxは現在のコンポーネントにスコープされるため使用できません(スタイルをglobalとしてマークしない限り)
  • fillを使用する場合、親要素はposition: relativeでなければなりません
    • これは、そのレイアウトモードで画像要素を適切に描画するために必要です
  • fillを使用する場合、親要素はdisplay: blockでなければなりません
    • これは<div>要素のデフォルトですが、そうでない場合は指定する必要があります

使用例

レスポンシブ

responsive

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Responsive() {
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Image
alt="Mountains"
// インポートされた画像は
// 自動的にwidthとheightがセットされる
src={mountains}
sizes="100vw"
// 画像の表示を全幅にする
style={{
width: '100%',
height: 'auto',
}}
/>
</div>
)
}

コンテナ要素のサイズに合わせる

Fill Container

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Fill() {
return (
<div
style={{
display: 'grid',
gridGap: '8px',
gridTemplateColumns: 'repeat(auto-fit, minmax(400px, auto))',
}}
>
<div style={{ position: 'relative', height: '400px' }}>
<Image
alt="Mountains"
src={mountains}
fill
sizes="(min-width: 808px) 50vw, 100vw"
style={{
objectFit: 'cover', // cover, contain, none
}}
/>
</div>
{/* グリッド上の他の画像 */}
</div>
)
}

背景画像

Background Image

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Background() {
return (
<Image
alt="Mountains"
src={mountains}
placeholder="blur"
quality={100}
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/>
)
}

さまざまなスタイルで使用されている Image コンポーネントの例については、Image Component Demo  を参照してください。

その他の属性

next/imageコンポーネントで利用可能なすべての属性を見る。

設定

next/imageコンポーネントと Next.js の画像最適化 API は、next.config.jsファイルで設定できます。これらの設定により、リモート画像を有効にしたり、カスタム画像のブレークポイントを定義したり、キャッシュ動作を変更したりできます。

詳しくは、画像設定に関する完全な文書を参照してください。

API リファレンス

next/image API の詳細

/docs/app-router/api-reference/components/image