2022/09/20

テクノロジー

AVIFがかわいそうだったので少しでも認知度が上がってほしい

この記事の目次

    社内でWebアプリケーションの要件についての話がされている際のことです。
    画像の拡張子について要件があったんですが、そこには基本的にWebPで、表示できないブラウザはPNGにするという旨が記載されていました。

    AVIF君かわいそう、その場での私の気持ちは一つです。

    そんなわけで、不思議と話に上がらないAVIFフォーマットとそれへの変換、フロントエンド周りの話をしてゆこうかと思います。

    AVIF とは

    AVIF (AV1 Image File Format) は、 AV1ビットストリームを HEIF (High Efficiency Image File Format) コンテナーにエンコードした、強力でオープンソース、ロイヤリティフリーのファイル形式です。 (中略) 一般的に、 AVIF は WebP よりも圧縮率が高く、同じ JPG セットで中央値 50% 対 30% の圧縮率です -- 引用元:[画像ファイルの種類と形式ガイド__MDN]

    見ての通り、ここまで読む限りではWebPよりも優れた形式です。
    こんな優れた形式がなぜ使われていないのか、理由はいくつか考えられますが、個人的には知名度とブラウザ対応かと思います。

    ブラウザ対応範囲

    対応ブラウザは、Chrome, Opera, Firefoxです。
    WebPの対応ブラウザはChrome, Edge, Firefox, Opera, Safariなので、比較するとEdgeとSafari対応がされていません。
    (ユーザーが意図的に古いバージョンを用いている場合については考えないものとする)

    SafariとEdgeに対応していないことは地味に辛く、MDNにおいてもAVIFを用いる場合は <picture>要素を使って他の拡張子に対応するようにしましょうと書かれています。

    <picture>要素は以下のように使用します。

    <picture>
      <source srcset="/cat.avif" type="image/avif" />
      <source srcset="/cat.webp" type="image/webp" />
      <img src="/cat.jpg" alt="cat" />
    </picture>

    使用しているブラウザに合わせて、上から順に優先して表示します。
    そのため、例えば上記のコード内のavifとwebpを入れ替えると、webpが優先して使用されます。

    ちなみに、<picture> はIE以外の全ブラウザが対応しているので、IEが寿命を迎えた今、全ブラウザが対応している要素です。

    AVIFに画像を変換する

    個人的には、sharpをお勧めします。
    理由は単に、node.jsを入れるのが楽なのと、Next.jsの画像最適化機能に使われているのである程度信用があるためです。

    単純に変換するだけであれば、以下のコードで変換できます。

    #!/usr/bin/env zx
    
    const sharp = require('sharp')
    
    sharp(argv.p)
      .avif()
      .toFile(`${argv.p}.avif`)

    コマンドライン引数の取得が手間だったためzxを使用していますが、cli上からファイル名を取得するためだけに使用しているので無視していただいて問題ありません。

    このように、ファイル形式を変えるだけであればこうして簡単にできます。

    ちなみに、こうして変換した場合のファイルサイズについては以下の通りとなっています。

    jpg (元画像)WebPAVIF
    ファイルサイズ1059403132415309
    比率100%29.6%14.5%

    写真は、適当な猫の画像を使用しました。
    見ての通り、WebPと比較してもさらに小さいことが良くわかると思います。
    かなり楽に変換できるので、指定したディレクトリのファイルをWebPとAVIFに変換するなんてコードを書くのも楽です。

    素書きのHTMLで使う場合は、こうして作ったファイルを<picture>で出してしまいましょう。

    Next.jsにおけるAVIF

    AVIFは、Next.jsの画像最適化対象です。
    ただし、変換速度がWebPと比較すると遅いため、デフォルトの設定ではAVIFは変換対象になっていません。

    使用する場合は、以下のように設定を next.config.jsに追加してください。

    const nextConfig = {
      images: {
        formats: ['image/avif', 'image/webp'],
      }
    }
    
    module.export = nextConfig

    これで、AVIFの画像最適化が有効になります。
    もし使用する場合は、キャッシュと相談して使うようにしてください。

    ※本記事は2022年09月時点の情報です。

    著者:マイナビエンジニアブログ編集部