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&w=1080&q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&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&w=128&q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=256&q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=256&q=75"
style="color: transparent;">
幅100px指定で適用された画像
imageSizes が sizes の prop を提供する画像にのみ使用されるためです。これは、画像が画面の全幅よりも小さいことを示します。したがって、imageSizes のサイズはすべて、deviceSizes の最小サイズよりも小さくする必要があります。
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&w=640&q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=750&q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=828&q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1080&q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1200&q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1920&q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&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&w=640&q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=750&q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=828&q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1080&q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1200&q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1920&q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&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&w=1080&q=50 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=50 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&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&w=1080&q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75"
style="color: transparent;">
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&w=1080&q=75 1x,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2x"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&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&w=256&q=75 256w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=384&q=75 384w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=640&q=75 640w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=750&q=75 750w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=828&q=75 828w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1080&q=75 1080w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1200&q=75 1200w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=1920&q=75 1920w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=2048&q=75 2048w,
/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&q=75 3840w"
src="/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fsample.3777ef8f.jpg&w=3840&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