HugoでWebPとAVIF形式の画像ファイルを扱う
WebP や AVIF 形式の画像ファイルは、より高品質でありながらファイルサイズが小さいため、近年注目を集めています。しかし、これらの画像形式に対応していないブラウザが存在しているため、後方互換性に注意を払い実装する必要があります。
本記事では、Hugo で WebP や AVIF 形式の画像ファイルを扱う方法を紹介します。
AVIF/WebP の HTML マークアップについて
まず基本となる AVIF/WebP のマークアップは下記の通りです。
<picture>
<source srcset="hogehoge.avif" type="image/avif" />
<source srcset="hogehoge.webp" type="image/webp" />
<img
src="hogehoge.jpg"
alt="hogehoge is cool"
loading="lazy"
decoding="async"
width="400"
height="300"
/>
</picture>
WebP/AVIF に対応しているブラウザであれば source タグに指定したファイルを描画し、そうでない場合は img タグで指定した画像が表示されます。
単純な HTML ファイルであればこの通りマークアップすることで事足りますが、Hugo では markdown 記法で挿入した画像を変換する必要があります。
Hugo のデフォルトテンプレートをオーバーライドする
Hugo の Markdown Render Hooks と呼ばれる機能を使うことで、markdown のレンダリングを行うテンプレートをカスタマイズすることができます。
画像をレンダリングするテンプレートを上書くには、下記ディレクトリ構造にrender-image.html
という名前でファイルを用意します。
layouts/
└── _default/
└── _markup/
└── render-image.html
render-image.html のコード
私は下記のように render-image.html を実装しています。
画像のマークアップ部分は様々な箇所で使い回せるため、partials に置いて共通化しました。
render-image.html
{{ partial "atoms/picture.html" (dict "image" (.Destination | safeURL) "alt" .Text) }}
atoms/picture.html
<picture>
{{ $isAVIF := eq (path.Ext .image) ".avif" }}
{{ $isWebP := eq (path.Ext .image) ".webp" }}
{{ $imgSrc := "" }}
{{ if or $isAVIF $isWebP }}
{{ $type := "" }}
{{ if $isAVIF }}
{{ $type = "avif" }}
{{ else if $isWebP }}
{{ $type = "webp" }}
{{ end }}
<source srcset="{{ .image }}" type="image/{{ $type }}" />
{{ $jpgPath := replace .image (printf ".%s" $type) ".jpg" }}
{{ $jpgPathStatic := printf "static/%s" $jpgPath }}
{{ if (fileExists $jpgPathStatic) }}
{{ $imgSrc = $jpgPath }}
{{ end }}
{{ $pngPath := replace .image (printf ".%s" $type) ".png" }}
{{ $pngPathStatic := printf "static/%s" $pngPath }}
{{ if (fileExists $pngPathStatic) }}
{{ $imgSrc = $pngPath }}
{{ end }}
{{ else }}
{{ $imgSrc = .image }}
{{ end }}
<img
src="{{ $imgSrc }}"
{{ with .alt }}alt="{{ . }}"{{ end }}
loading="lazy"
decoding="async"
{{ with imageConfig (printf "/static%s" $imgSrc) }}
width="{{ .Width }}" height="{{ .Height }}"
{{ end }}
/>
</picture>
まとめ
実は AVIF/WebP が Microsoft edge で未対応だったことを知らず、調査が不十分な状態で AVIF に置き換えていたのですが、あとになって edge で画像が表示できていないことに気づき修正しました。edge も早く対応してくれると嬉しいですね。
ともあれ、これで AVIF/WebP を使うことでサイトの読み込み速度を向上させ、ユーザーエクスペリエンスを向上させることができます。やったぜ!