WordPressの画像をWebPにしてページの表示を高速化!
概要
- jpg,gif,pngに変わるWebPがそろそろ普及しだしてきたので流れに乗ってみます。
- Lighthouseでページ表示のパフォーマンスを見ると、画像によっては容量が半分ぐらいになるとの表示がありました。
Googleの示した事例では、ファイルサイズは非可逆圧縮モードで(同一画像、同等画質の)JPEGと比較して25-34%小さくなり、可逆圧縮モードでPNGと比較して28%小さくなるとしている。
設定前のスコアはこちら。

設定
WordPressでこのWebPを扱おうとなると結構厄介で、なんか怪しいプラグインもあったりするので今まで何回かトライしましたが断念しました。
今回は、こちらのプラグインを使って実現しました。
設定手順
インストール時に、wp-contentディレクトリ直下にファイルが作成されるので、PHPが動いているユーザに対して書き込み権限を一時的に与えておく必要があります。
chmod a+w wp-content普通にプラグインを上記からインストールします。
wp plugin install webp-converter-for-media --activateこのサービスは、PHP-FPMとnginxによって稼働しているので、こちらのページを参考にしてnginxの設定を変更します。
私の環境では差分は以下のような感じです。
[root@ip-172-26-2-21 nginx]# git diffdiff --git a/nginx/conf.d/triathlon.teraren.com.conf b/nginx/conf.d/triathlon.teraren.com.confindex 3e174ae..7d3155c 100644--- a/nginx/conf.d/triathlon.teraren.com.conf+++ b/nginx/conf.d/triathlon.teraren.com.conf@@ -1,3 +1,12 @@+map $http_accept $load_avif {+ ~image/avif "/wp-content/uploads-webpc/$path.$ext.avif";+}+map $http_accept $load_webp {+ ~image/webp "/wp-content/uploads-webpc/$path.$ext.webp";+}+++ server { listen 443 ssl http2; listen [::]:443 ssl http2;@@ -10,8 +19,16 @@ server { ssl_certificate_key /etc/letsencrypt/live/teraren.com/privkey.pem; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m;+ include global/ssl.conf;
+ location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif)$ {+ add_header Vary Accept;+ add_header Cache-Control "private" always;+ expires 365d;+ try_files $load_avif $load_webp $uri =404;+ }+ location / { root /home/matsu/Sites/teraren.com/triathlon; index index.php index.html index.htm;diff --git a/nginx/mime.types b/nginx/mime.typesindex 2961256..6a69410 100644--- a/nginx/mime.types+++ b/nginx/mime.types@@ -23,6 +23,7 @@ types { image/x-icon ico; image/x-jng jng; image/x-ms-bmp bmp;+ image/avif avif;
font/woff woff; font/woff2 woff2;あとは、nginxをreloadします。
systemctl reload nginxあとは、WordPressの管理画面上でWebP画像を生成すれば終わりです。

すべての画像は、wp-content/webpc-passthru.phpを経由して、webp画像があればそれを返して、存在していなければ今までと同じ用にgifやpngファイルを返却します。
Performanceスコアが42から56へ改善されました。なぜかSEOなどのスコアも上がっている。。。

プラグインの内部動作
このプラグイン、どうやって動作しているかというのがちょっと興味深いです。
オリジナルの画像は保持しておいて変更はしません。画像をアップロードした直後にWordPressが自動で生成する7個ぐらいのサムネイル画像をWebPに変換する対象としています。
プラグインでの管理画面でのRegenerate imagesは何をやっているかというと、サイズごとの画像をwebpに変換しつつ、もしwebpのほうが容量が大きければ変換は行わないようになっています。
その前提で、wp-content/webpc-passthru.phpがwebpファイルの有無を判定してブラウザに適切なファイルを返却しています。
また、ドキュメントでは分かりづらいですが、この設定を.htaccessの方にすればPHP側でのファイル判定を行わないで、Webサーバ側に判定を任せるようになります。(=wp-content/webpc-passthru.php を使わなくなる)

nginxなのに、via .htaccessを選ぶとエラーの表示は出ちゃいますが、nginxの設定をちゃんと行っていれば問題ないので無視します。

実験
対象のURL:/uploads/2022/01/image-4.png
WebPファイルのURL: https://triathlon.teraren.com/wp-content/uploads-webpc/uploads/2022/01/image-4.png.webp
普通にpngをリクエストしてみると、普通にpngファイルが返却される。content-typeヘッダと、content-lengthヘッダで判断できます。
$ curl -I /uploads/2022/01/image-4.pngHTTP/2 200server: nginx/1.20.0date: Mon, 10 Jan 2022 15:46:10 GMTcontent-type: image/pngcontent-length: 179549last-modified: Mon, 10 Jan 2022 15:09:19 GMTetag: "61dc4c1f-2bd5d"expires: Tue, 10 Jan 2023 15:46:10 GMTcache-control: max-age=31536000vary: Acceptcache-control: privateset-cookie: uid=JsIFgGHcVMKhc1BNAwNBAg==; path=/accept-ranges: byteswebpをacceptできる用に偽装してリクエストすると、webpが返却されます。
$ curl -H 'accept: image/webp' -I /uploads/2022/01/image-4.pngHTTP/2 200server: nginx/1.20.0date: Mon, 10 Jan 2022 15:46:40 GMTcontent-type: image/webpcontent-length: 59626last-modified: Mon, 10 Jan 2022 15:09:22 GMTetag: "61dc4c22-e8ea"expires: Tue, 10 Jan 2023 15:46:40 GMTcache-control: max-age=31536000vary: Acceptcache-control: privateset-cookie: uid=JsIFgGHcVOChc1BNAwNEAg==; path=/accept-ranges: bytesなかなか頭がよいですね。拡張子がpngでリクエストをしていますが、ファイルのmimeはwebpなので、ちょっと混乱するかもしれませんが、速度優先ってことで良いことにしましょう。
追記
もう少し、スコアを向上させました。
パフォーマンス改善を行うための残り要素は、外部サイトからのWidget読み込みに関連しているので一旦終わり。
