next/imageが遅いのでやめた

公開 ( 更新)履歴 (4)

iPadケースを作った記事の画像が読み込みに2秒以上かかることがあり閲覧に支障があったため改善したまとめです。

修正前の画像読み込みの具合
修正前の画像読み込みの具合

next/imageは画像を調整してくれるのはいいのですが、元の画像が3MBくらいでキャッシュがないと表示まで3秒くらいかかっていました。ここは私の個人サイトなので編集がなければコンテンツは変わらないので、事前にいい具合のサイズの画像を生成しておいてブラウザに選択させるようにしました。実装した機能は以下の通りです。

  1. srcとpublicの画像を列挙する

  2. それぞれについて 幅(300, 400, ..., 1800) × 形式(オリジナル, webp, avif) の画像を生成する

    • 例えば 幅(300, 400, 800) × 形式(jpeg, webp, avif) なら9種類

  3. 生成した画像の一覧を使って {元ファイル}.component.tsx を生成する(このファイルは.gitignoreする)

  4. 画像がすでに生成してあれば省略する(.gitignoreしてるのでコンポーネントの生成は毎度やる)

{元ファイル}.component.tsxは例えばこんな感じです。

生成されるコンポーネントの例
  1. import type {DetailedHTMLProps, ImgHTMLAttributes} from 'react';
  2. const Image = (
  3. props: DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>,
  4. ) => <picture style={{aspectRatio: '1526/1266'}}>
  5. <source srcSet="/images/v1/Qb2kzaQ4/300w.webp 300w, /images/v1/Qb2kzaQ4/400w.webp 400w, /images/v1/Qb2kzaQ4/500w.webp 500w, /images/v1/Qb2kzaQ4/600w.webp 600w, /images/v1/Qb2kzaQ4/800w.webp 800w, /images/v1/Qb2kzaQ4/1000w.webp 1000w, /images/v1/Qb2kzaQ4/1200w.webp 1200w, /images/v1/Qb2kzaQ4/1500w.webp 1500w" type="image/webp" />
  6. <source srcSet="/images/v1/Qb2kzaQ4/300w.avif 300w, /images/v1/Qb2kzaQ4/400w.avif 400w, /images/v1/Qb2kzaQ4/500w.avif 500w, /images/v1/Qb2kzaQ4/600w.avif 600w, /images/v1/Qb2kzaQ4/800w.avif 800w, /images/v1/Qb2kzaQ4/1000w.avif 1000w, /images/v1/Qb2kzaQ4/1200w.avif 1200w, /images/v1/Qb2kzaQ4/1500w.avif 1500w" type="image/avif" />
  7. <img alt="" {...props} srcSet="/images/v1/Qb2kzaQ4/300w.png 300w, /images/v1/Qb2kzaQ4/400w.png 400w, /images/v1/Qb2kzaQ4/500w.png 500w, /images/v1/Qb2kzaQ4/600w.png 600w, /images/v1/Qb2kzaQ4/800w.png 800w, /images/v1/Qb2kzaQ4/1000w.png 1000w, /images/v1/Qb2kzaQ4/1200w.png 1200w, /images/v1/Qb2kzaQ4/1500w.png 1500w" />
  8. </picture>;
  9. export default Image;

この対策により表示にかかる時間(の最大値)は3,000msから200ms以下になりました。

修正後の画像読み込みの具合
修正後の画像読み込みの具合

訂正 #link

このツイートの50msはおそらくx-vercel-cache: HITのを見ているので正しくないです。

参考文献 #link

  1. MDN Web Docs

    1. <picture>: The Picture element

    2. <source>: The Media or Image Source element

    3. <img>: The Image Embed element