約20行!WordPressでプラグインに頼らないWebP対応
最新のSafariもWebPに対応し、いよいよWebP元年という感じがします。個人で運用しているWordPressサイトにWebPをプラグインを使わずに導入した方法です。
とりあえず結論
結果だけほしい人は下記ファイルにそれぞれ追加し、hoge.jpg
とhoge.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に変換するのが面倒なら、コマンド一発で画像を一括で変換するツールを作ったのでご活用ください。
Discussion