😉

Next.js 10のnext/imageによる画像最適化を試してみた

2020/10/28に公開
2

概要

Next.js 10が発表されたのでnext/imageによる画像最適化を試してみました。

https://nextjs.org/blog/next-10

試し方

npx create-next-app
next dev

します。
package.json
10.0.0になってました!

こちらを見ながら試してみます。
https://nextjs.org/docs/basic-features/image-optimization
https://nextjs.org/docs/api-reference/next/image

画像はフリー素材のこちらを使います。
フリー画像

next/images

画像はpublic/free.jpgに入れています。
widthやheightを書かずにただ書くとエラーになります。

import Image from 'next/image';
<Image src={"/free.jpg"} />

怒られた
両方書くと動きます。片方だけだとエラーになります。

<Image src={"/free.jpg"} width={1920} height={1281} />

アスペクト比を無視すると画像が歪みます。

<Image src={"/free.jpg"} width={1000} height={100}  />

unsizedだと、1200px * 801pxになっていました。(元画像は1920 * 1281)

<Image src={"/free.jpg"} unsized />

中身

こんな感じになっていました。width、heightで指定したサイズ以下の複数サイズで、適切なサイズのものが自動で提供されるようになっていました。
unsizedだと1200px以下で設定されます。
幅はnext.config.jsのdeviceSizesで変えられます。

画像のサイズなどはURLのクエリパラメータで制御しているようです。
例えばqの値を上下させると画質、ファイルサイズも上下します。

http://localhost:3000/_next/image?url=%2Ffree.jpg&w=1200&q=75

WebPフォーマットに対応、が

元画像のサイズは695KBでjpgです。
Chromeで表示した場合は image/webp としてファイルサイズは130KBになっていました。
Safari(webP非対応)で表示した場合は image/png としてファイルサイズは1.6MBになっていました。
なぜpngでサイズ倍にした!!
safariの開発者ツール詳しくないですが見方間違ってますかね??

追記:
10.0.1で直ってました!
がんがんjpg使いましょう。

外部ファイルの読み込み

外部ソースもいけるのかなと思いやってみたところ、エラーになってしまいました。

Unhandled Runtime Error
Error: Invalid src prop (https://hogehogehoge.net/hogehoge/) on `next/image`, hostname is not configured under images in your `next.config.js`

next.conig.jsにloaderとpathを設定するといけそうなのですが、現時点ではVercel、Imgix、Cloudinary、Akamaiしか対応してなさそう?
対応できても、path: '/_next/image',の部分も上書きすることになってしまうので、完全に外部に出すか、内部のみでのどちらかしかできないんですかね?

追記:
と思っていたらdomains指定で普通にできました。
公式に対応しているとどう違うのかなどもわかったら追記しますー

遅延ロード

ビューポートが近づくと画像をロードする機能で、正常に動いています。
画像の上200pxぐらいから反応してダウンロードしてました。

初期のぼかし画像表示

なさそうです。gatsby-imageのようにインライン化したぼかし画像が欲しかったですね。

小さい画像はインライン化される?

800バイトのsvg画像で試した限りではされないようです。

結論

なんでwebp非対応ブラウザだとjpgがpngでサイズ2倍になるの?
他は大丈夫そうです。
next-optimized-imagesがいまいちだったので、不思議サイズ問題だけ解決してくれれば。

追記:
10.0.1でjpgのサイズがおかしくなる問題が直ったので使っていきます!

Discussion

catnosecatnose

WebP未対応のSafariでJPEGがPNGになってしまう問題、ちょっと調べてみました。
下記の部分が原因っぽいですね。
https://github.com/vercel/next.js/blob/a351bd6aaf36b4f3b5e6d98e362873810838a9e4/packages/next/next-server/server/image-optimizer.ts#L52

next/imageコンポーネントではURLを生成しているだけで、実際の画像の生成はnext-server/server/image-optimizer.tsで行われています。)

このimage-optimizerでは、クライアントから送られてきたAcceptヘッダーに従ってContent-Typeを決めて画像を生成します。
iOS13以前だと画像のAcceptヘッダーはデフォルトでimage/png, image/svg+xml...から始まるようで(参考)それによりPNG画像が返ってきてしまうと。

とりあえずの対処方法がないか調べてみます。