Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

Next.js10新機能 next/imageを使ってみた

こんにちは、フロントエンドエンジニアの松尾です。

2020年10月27日にNext.js10がリリースされ、パフォーマンスを改善するための20個を超える新しい機能が追加されました。

nextjs.org

私たちフロントエンドチームでも、プロジェクトにNext.js10を導入しており様々な恩恵を得ています。

本記事では、その中でも最も便利だと感じたnext/imageについてご紹介したいと思います。

next/imageとは

next/imageとは、画像の表示を自動で最適化してくれるコンポーネントです。

主に以下の最適化を行います。

  1. WebPフォーマット*1変換(対応ブラウザのみ)
  2. 画像遅延読み込み(Lazy Load)
  3. レスポンシブ対応

導入方法

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です。

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の魅力の一つです。

それぞれの引数の詳細は下記の公式ドキュメントに記載されてますので、興味のある方は見てみてください。

nextjs.org

まとめ

以上next/imageの導入方法・最適化についての説明でした。

画像はWebページのトータルバイト数のうち50%を占めていると言われてますので、next/imageを積極的に活用しパフォーマンスを改善していきましょう!

最後になりますが、Wizではエンジニアを募集中です!

興味のある方は是非覗いてみてください↓

careers.012grp.co.jp

*1:Google開発の画像フォーマット。ファイルサイズを大幅に軽量化できる。