約20行!WordPressでプラグインに頼らないWebP対応

3 min read読了の目安(約3200字

最新のSafariもWebPに対応し、いよいよWebP元年という感じがします。個人で運用しているWordPressサイトにWebPをプラグインを使わずに導入した方法です。

とりあえず結論

結果だけほしい人は下記ファイルにそれぞれ追加し、hoge.jpghoge.jpg.webpという名前のファイルでアップロードすればOKです。

▼functions.php

/**
 * Allow Webp
 */
function custom_mime_types( $mimes ) {
  $mimes['webp'] = 'image/webp';
  return $mimes;
}
add_filter( 'upload_mimes', 'custom_mime_types' );

/**
 * 大きな画像に_scaledという名前をつけない
 */
add_filter("big_image_size_threshold", "__return_false");

▼htaccess

<IfModule mod_rewrite.c>
  # Rewriteモジュールを有効にする
  RewriteEngine On

  # ブラウザから送信されるAcceptリクエストヘッダがimage/webpを含む場合のみ
  # 後続のRewriteRuleを適用する
  RewriteCond %{HTTP_ACCEPT} image/webp

  # WebP版のファイルがある場合のみ後続のRewriteRuleを適用する
  # SCRIPT_FILENAMEを使うことでサブディレクトリの補完が不要に
  RewriteCond %{SCRIPT_FILENAME}.webp -f

  # *.jpg、*.pngファイルを*.webpファイルに内部的にルーティングする
  # Content-Typeはimage/webpにする
  RewriteRule .(jpe?g|png)$ %{REQUEST_URI}.webp [T=image/webp,E=accept:1]
</IfModule>

<IfModule mod_headers.c>
  # 環境変数_image_requestが真の(上記SetEnvIfが設定された)場合、
  # VaryレスポンスヘッダにAcceptを追加する
  Header append Vary Accept env=_image_request
</IfModule>

<IfModule mod_mime.c>
  # 拡張子.webpファイルはContent-Typeとしてimage/webpを返す
  AddType image/webp .webp
</IfModule>

細かい解説

WordPressのWebP化にあたり2つの作業をしています。

  • WebPファイルアップロードの許可
  • WebP対応環境はwebpを配信し、非対応の環境にはjpgでフォールバックする
    フォールバックに関しては最新じゃないSafariやIE11のほか、OGPなどのクローラーも対応していないものがある(?)のでフォールバック処理は入れておいたほうが良いです。

画像の運用ですが、hoge.jpgに対してhoge.jpg.webpという画像を用意します。hoge.webpにしないのはhtaccessによる振り分け処理の兼ね合いです。

WebPのアップロードを許可

デフォルトでWordPressはWebPのアップロードが許可されていないのでテーマのfunctions.php

/**
 * Allow Webp
 */
function custom_mime_types( $mimes ) {
  $mimes['webp'] = 'image/webp';
  return $mimes;
}
add_filter( 'upload_mimes', 'custom_mime_types' );

を追加してアップロードを許可します。wp-config.php

define( 'ALLOW_UNFILTERED_UPLOADS', true ); // WordPress5.7ではダメだった…

を追加すれば大丈夫との情報もありましたがWordPress5.7ではダメでした。もう一つfunctions.php

/**
 * 大きな画像に_scaledという名前をつけない
 */
add_filter("big_image_size_threshold", "__return_false");

を追加します。これはWordPress5.3から大きな画像(2560px以上?)をアップロードした場合にhoge-scaled.jpgというsuffixつきのファイル名になってしまうのを防ぎます。suffixがつけられると上記のファイル名の運用ができなくなってしまいます。大きな画像を使わないのであればなくても大丈夫です。

htaccssによる画像の配信振り分け

ブラウザのヘッダ情報をみてwebp対応ブラウザにはhoge.jpgという要求に対してhoge.jpg.webpというファイルを返す処理を追加します。細かい内容については参考にした、『.htaccessによるWebPの選択的レスポンスとその問題点と改善案 - Qiita』をご参照ください。

自分の環境だとWordPressファイルはドメインルート直下におかずにwordpressのようなフォルダの中にいれていたので少し改変しています。

WordPressでWebPを使う

WordPressで記事を作るときはhoge.jpgの方を使います。HTMLとしてはhoge.jpgとして出力されますが、サーバーサイドの処理で送られてくるのはhoge.jpg.webpになります。デベロッパーツールのネットワークタブでhoge.jpgのTypeがwebpになっていれば成功です。

これで高画質・低容量なWebPファイルをWordPressでプラグインを使わずとも対応できます。

オプショナル:アートディレクションによる画像サイズの出しわけを無効にする

これは任意の設定ですが、WordPressの投稿からの画像挿入の場合、表示幅に合わせて画像サイズを出し分ける、アートディレクション機能があります。(WP独自の機能ではなく、HTMLのsrcset属性による出し分け)表示サイズが小さい場合、リサイズされた画像が表示されます。WebPとして用意しているのがオリジナルサイズの画像だけなのでjpgで配信されてしまいます。

そのsrcsetを出し分けを無効にするには下記コードをfunctions.phpに追加します。

add_filter( 'wp_calculate_image_srcset_meta', '__return_null' );

これでアートディレクション機能を無効にし、指定の画像のみになります。

おまけ

WebPに変換するのが面倒なら、コマンド一発で画像を一括で変換するツールを作ったのでご活用ください。

https://github.com/ics-nishihara/simple-image-optimiser