WebP(ウェッピー)対応はじめました!実装例とカンタン一括変換する方法


暑過ぎる夏到来!ということで冷やし中華はじめまし…
ではなく、WebP対応はじめました。暑さ関係なし。

WebPなんぞや?

  • Google開発のオープンな静止画フォーマット。ファイル拡張子「.webp
  • Googleが使用を推奨。データ容量がほかの画像フォーマットより軽い (圧縮率が高い)というメリットがある -> 軽量化・高速化に寄与
  • 可逆圧縮ならPNG画像と比べてサイズが26%小さくなり、非可逆圧縮ならJPG画像より25〜34%小さくなるらしい。JPG / PNG / GIF (アニメーション含む)に対しての代替となる

WebP小話

  • 読み方は「ウェッピー」。「チャッピー」「ヒッピー」「ホッピー」「ポリッピー」に語感が似ており何かファンシーな響き。声に出して読みたい画像フォーマット
  • 単語の頭と尾が大文字である。たくさんの人が語尾をうっかり小文字にしちゃうヤツだこれ…
  • けっこう古い (2010年に仕様公表)

ブラウザ対応状況を考慮した実装 (2019/8現在)

  • WebPはGoogle Chrome、Microsoft Edge、Firefoxで使用可。Apple Safariはそっぽ向いてる。IEはお察しください (泣)
  • 日本だと約45%のユーザーが利用可能で増加傾向にある (世界全体では80.53%)

 参考:https://caniuse.com/#search=webp

実装例

  • 方針:対応ブラウザではWebPを表示し、対応していないSafariとIE11ではJPG / PNG等を表示(フォールバック)する
    • picture要素を用いることで、対応状況に合わせた画像(形式)の出し分けが可能
    • IE11でpicture要素を使うために「Picturefill」JSライブラリを泣く泣く導入
HTML
<picture>
  <source type="image/webp" srcset="img/image.webp, img/[email protected] 2x"> <!-- WebP対応ブラウザはsourceを適用 -->
  <img src="img/image.png" alt="画像代替テキスト"> <!-- WebP非対応ブラウザはimg画像を表示 -->
</picture>

以下はIE11対応。webpack + babelなどでES5へのトランスパイルが必要

JavaScript
import picturefill from "picturefill";
picturefill();

または

HTML
<head><script src="/picturefill.js"></script>
</head>
  • アイコン、ロゴ、簡単なイラストなどベクター画像はSVG、写真とかそれ以外のラスター画像はWebP (JPG / PNGの代替)という得意分野で使い分けたい

WebPの作成・変換方法

[Windows編] 「WebPconv」デスクトップアプリで一括変換

  • Windowsのみ対応の無料デスクトップアプリ「WebPconv」を利用する。公式サイトの右サイドバーにある「Download Now」からPCへダウンロード
  • インストールが完了したら「WebPconv」を起動する。下のアプリUI画像の「+」ボタン押下で開くエクスプローラーからローカルディレクトリ+ファイルを選択(複数選択可) → 右のボタン押下で一括変換実行

[mac編] Homebrewで「cwebp」をインストール。シェルスクリプトで一括変換処理

  • macの場合はコマンド(ターミナル)でWebPへ一括変換処理する。黒い画面アレルギーの人スマソ…
  • cwebp」というエンコーダー(WebP変換)ツールをHomebrew経由でインストール
CLIでインストール
brew install webp
シェルスクリプトで一括変換(ループ処理)
# cdコマンドで対象画像ファイルのあるディレクトリへ
for file in *; do cwebp "$file" -o "${file%.*}.webp"; done

そのほかのWebP作成・変換ツール(単一処理)

プラスで表示高速化にチャレンジ

リソースを先読みする

  • ファーストビューに比較的大きめの画像(ヒーロー画像、メインビジュアルなど)が存在する場合、当該画像をlink rel="preload"で先読み指定して、初期画面表示の高速化を試みる
  • 他にもさまざまなコンテンツを先読みできる。適切に使いたい
    -> https://developer.mozilla.org/ja/docs/Web/HTML/Preloading_content
HTML
<head>
  ~
  <link rel="preload" href="img/hero.webp" as="image">
  ~
</head>

画像を非同期デコードして表示高速化

すべての画像をimg decoding="async"で非同期読み込みし、順番待ちをなくして表示高速化を試みる

HTML
<body>
  ~
  <img decoding="async" src="img/photo1.webp">
  <img decoding="async" src="img/photo2.webp">
  ...

ズッコケ豆情報:Chrome76(75?)で実装予定と噂されたloading属性(loading="lazy"・Lazy Load)は現状実装されていない → 後日、76で追加実装された模様 (2019/8/15記)

パフォーマンス検証結果

A. JPGのみ
B. WebPのみ
C. WebP + link rel="preload" + img decoding="async"

上記パターンでサーバーアップし、1画面あたり20枚の画像を10回読み込み、Chrome DevToolsで中央値を取る形で検証したが、読み込み速度(load)にあまり有意な差は認められなかった。ページ容量は「A > B = C」。
理論上読み込み速度は「C < B < A」となるはずなので、いずれもっと厳密な条件で検証をしてみたい。

では。

参考記事