841-biborokuWebフロントエンドの備忘録

next/imageの<Image>コンポーネントのプロパティとhtmlの出力タグを見比べてみる

next/imageの<Image>コンポーネントを使ったときに、どのような結果が得られるか以下の項目に注目して比較してみました。

  • 必須・任意オプションの使い方
  • 出力されたhtmlタグ
  • 画像の容量・ファイルタイプ(形式)
  • 画像ファイルの幅

条件

用意した画像

1000x1000px サイズ:1.19MB(圧縮していない) タイプ:jpeg

next.config.js

構成オプションは未設定=デフォルトのまま

deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840]

imageSizes: [16, 32, 48, 64, 96, 128, 256, 384]

必須プロパティを設定したとき

用意した画像を静的インポートし、必須のプロパティaltを設定してみます。

srcに静的インポートとfillをしていない場合は、幅と高さの設定が必須となります。

import Image from "next/image";
import sample from "@/public/images/sample.jpg";

<Image src={sample} alt="サンプル画像" />
<Image src={sample} width={1000} height={1000} alt="サンプル画像" />
<img alt="サンプル画像" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1" style="color:transparent"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75">

サイズ:133kB タイプ:webp

静的インポートした場合、幅と高さを指定しなくても同じ出力結果になります。


<Image src="/images/sample.jpg" width={1000} height={1000} alt="サンプル画像" />

インポートした画像ではなく、srcに画像パスを設定した場合はsrcsetのurlに指定されるURLから_next/static/mediaがなくなり指定した画像パスのみとなりました。

(※パスを指定する場合、width/heightが必須になります)

srcset="/_next/image/?url=%2Fimages%2Fsample.jpg~

幅1000px指定で適用された画像

💡width/heightに100pxを設定した場合どうなる?

<img alt="サンプル画像" loading="lazy" width="100" height="100" decoding="async" data-nimg="1"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=128&amp;q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=256&amp;q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=256&amp;q=75"
style="color: transparent;">

幅100px指定で適用された画像


imageSizes が sizes の prop を提供する画像にのみ使用されるためです。これは、画像が画面の全幅よりも小さいことを示します。したがって、imageSizes のサイズはすべて、deviceSizes の最小サイズよりも小さくする必要があります。

引用元:next/image | Next.js


imageSizesのデフォルト

imageSizes: [16, 32, 48, 64, 96, 128, 256, 384]

オプションプロパティを設定したとき

fill={true}

親要素に対して塗りつぶされるので画像には幅と高さを設定せず、.boxにposition:relativeを設定しています。

<div className={styles.box}>
  <Image src={sample} fill alt="サンプル画像" />
</div>
<img alt="サンプル画像" loading="lazy" decoding="async" data-nimg="fill" sizes="100vw"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=640&amp;q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=750&amp;q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=828&amp;q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1200&amp;q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1920&amp;q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75"
style="position: absolute; height: 100%; width: 100%; inset: 0px; color: transparent;">

サイズ:133kB タイプ:webp

fill={true} style={{objectFit: "cover"}}

塗りつぶしにobject-fit:coverを適用

<Image src={sample} fill style={{objectFit: "cover"}} alt="サンプル画像" />
<img alt="サンプル画像" loading="lazy" decoding="async" data-nimg="fill"
style="position:absolute;height:100%;width:100%;left:0;top:0;right:0;bottom:0;object-fit:cover;color:transparent"
sizes="100vw"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=640&amp;q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=750&amp;q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=828&amp;q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1200&amp;q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1920&amp;q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75">

サイズ:133kB タイプ:webp

styleを追加しただけなのでサイズ・タイプに変化はありません。

quality={50}

1~100(低品質~高品質)の間で品質を指定します。

<Image src={sample} quality={50} alt="サンプル画像" />
<img alt="サンプル画像" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=50 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=50 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=50"
style="color: transparent;">

quality={50} サイズ:98.1kB タイプ:webp

quality={25} サイズ:66.7kB タイプ:webp

qualityを指定しない場合、q=75が自動で設定されます。

unoptimized

trueで品質・サイズ・形式を変更せずそのままを表示します。

<Image src={sample} unoptimized alt="サンプル画像" />
<img alt="サンプル画像" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1"
src="/_next/static/media/sample.3777ef8f.jpg" style="color: transparent;">

サイズ:1.3MB タイプ:jpg

placeholder="blur" blurDataURL="data:image/webp;base64,xxxxx"

<Image
  src={sample}
  placeholder="blur"
  blurDataURL="data:image/webp;base64,xxx"
  alt="サンプル画像"
  />
<img alt="サンプル画像" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75"
style="color: transparent;">

サイズ:133kB タイプ:webp


https://blurred.dev/

blurDataURLに設定するblur画像をbase64に変換してくれるジェネレータ

priority={true}

デフォルトはfalse=遅延読み込みされる設定になっています。

Next.jsの公式ではLCPで検出された画像に適用するようにあります。

ファーストビュー(メインビジュアル)に使用するのがいいかと思います。

<Image src={sample} priority alt="サンプル画像" />
<img alt="サンプル画像" width="1000" height="1000" decoding="async" data-nimg="1"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75"
style="color: transparent;">

サイズ:133kB タイプ:webp


imgタグからloading="lazy"が消え画像の遅延読み込みはされません。

sizes={}

<Image
    src={sample}
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
    alt="サンプル画像"
   />
<img alt="サンプル画像" loading="lazy" width="1000" height="1000" decoding="async" data-nimg="1"
sizes="(max-width: 768px) 100vw,
(max-width: 1200px) 50vw,
33vw"
srcset="
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=256&amp;q=75 256w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=384&amp;q=75 384w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=640&amp;q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=750&amp;q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=828&amp;q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1080&amp;q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1200&amp;q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=1920&amp;q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=2048&amp;q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&amp;w=3840&amp;q=75"
style="color: transparent;">

💡どの画像が適用される?

📱ブラウザ幅375px・Retina2x

375x2=750px →750px幅の画像を読み込む

サイズ:92.2 kB タイプ:webp


💻ブラウザ幅300px

(max-width: 768px) 100vwが適用され100vw=300px →384pxの画像を読み込む

サイズ:37.6 kB タイプ:webp


💻ブラウザ幅760px

(max-width: 768px) 100vwが適用され100vw=760px →828pxの画像を読み込む

サイズ:104kB タイプ:webp


💻ブラウザ幅1100px

(max-width: 1200px) 50vwが適用され50vw=550px →640pxの画像を読み込む

サイズ:75.1kB タイプ:webp


💻ブラウザ幅2560px

33vwが適用され33vw=852.48... →1080pxの画像を読み込む

サイズ:133kB タイプ:webp


シェア