こんにちは、フロントエンドエンジニアの松尾です。
2020年10月27日にNext.js10がリリースされ、パフォーマンスを改善するための20個を超える新しい機能が追加されました。
私たちフロントエンドチームでも、プロジェクトにNext.js10を導入しており様々な恩恵を得ています。
本記事では、その中でも最も便利だと感じたnext/image
についてご紹介したいと思います。
next/imageとは
next/image
とは、画像の表示を自動で最適化してくれるコンポーネントです。
主に以下の最適化を行います。
導入方法
Next.jsにデフォルトで備わっているため、next/image
をimportするだけで使用することができます。
基本的に<img>
要素の書き方と変わりませんが、width・heightの記述は必須ですので注意が必要です。
import Image from "next/image" ~~~ <Image src="/free.jpg" width={600} height={400} />
画像比較
では実際に<img>
とnext/image
の比較をし、どのように画像の最適化が行われているか確認してみましょう。
比較対象として、以下のフリー画像を使用します。(free.jpg 843kb)
▼ コード
import Image from "next/image" const ImageArea = () => { return ( <> // 通常のimg <img src="/free.jpg" width={600} height={400} alt="通常のimg 林道"/> // next/imageのコンポーネント <Image src="/free.jpg" width={600} height={400} alt="next/imageのコンポーネント 林道"/> </> ) } export default ImageArea
表示を見てみると、同じ見た目の画像が並んでいることが確認できます。
こちらは最終的に吐き出されたnext/image
のHTMLです。
src/srcset属性を見てみると、/_next/image
を参照していることが確認できます。
/_next/image
はビルド時に生成される画像サーバーでして、こちらにパラメータを送ることで表示させる画像の切り替えを行っています。
以下は開発者ツールの画像読み込み箇所です。
next/image
ではWebPフォーマットでの表示となっており、ファイルサイズが70%程削減されています。
様々な画像で試してみたのですが、元々のファイルサイズが大きい画像ほど圧縮率が高い傾向があるようです。
次にレスポンシブ対応を確認してみましょう。
以下のように、next/image
の画像のみレスポンシブが適用されていることが確認できます。
width・heightの直接的な指定は、レイアウトまわりで色々と問題を引き起こす原因となるため避けがちです。
しかし、next/image
ではアスペクト比に基づいて自動的にレスポンシブ対応となるため問題なく指定することができます。
最後に遅延読み込みによる最適化です。
左の開発者ツールを見てみると、画像から200px程近づいた時に読み込みを行っていることが確認できます。
このように、next/image
では「サイズ最適化」「遅延読み込み」「レスポンシブ対応」の最適化を全て自動で行ってくれます。
外部ファイルの読み込み
外部サーバーから画像を読み込む場合、そのままURLを指定するとエラーが出てしまいます。
next.config.js
に以下の設定を追記することで、Next.js側がURLを認識し画像の読み込みをしてくれます。
module.exports = { images: { domains: ["example.com"], //ドメインを指定 }, }
オプション引数
next/image
では豊富なオプション引数が存在しています。
以下はオプション引数の設定例です。
<Image src={"/free.jpg"} // 画像へのパスまたはURL ※必須 width={600} // 画像の横幅 ※必須 height={400} // 画像の高さ ※必須 layout={"fill"} // レイアウト, "fill" | "fixed" | "intrinsic" | "responsive", default:"intrinsic" sizes={"80vw"} // メディアクエリのマッピングサイズ, default:"100vh" quality={50} // 画質, default:100 priority={true} // 表示優先度, default:false loading={"lazy"} // 遅延読み込み, "lazy" | "eager", default:"lazy" unoptimized={false} // 画像最適化, default:true objectFit={"cover"} // object-fit ※layout='fill'の場合 objectPosition={"50% 50%;"} // object-position ※layout='fill'の場合 />
対象の画像に合わせて柔軟に設定できることもnext/image
の魅力の一つです。
それぞれの引数の詳細は下記の公式ドキュメントに記載されてますので、興味のある方は見てみてください。
まとめ
以上next/image
の導入方法・最適化についての説明でした。
画像はWebページのトータルバイト数のうち50%を占めていると言われてますので、next/image
を積極的に活用しパフォーマンスを改善していきましょう!
最後になりますが、Wizではエンジニアを募集中です!
興味のある方は是非覗いてみてください↓