Apacheで運営しているサイトをお手軽にWebP対応する方法を紹介します。
※ nginxも対応可能です。記事の末尾に参考情報を記載しました。
Googleが推している新フォーマットなので、PageSpeed Insightsや、Lighthouseのスコアがわずかですがほぼ確実に上がります(笑)
さて、方法は次の3ファイルをWebサーバーに設置して、cronによる定期処理を登録するだけです。
- WebPへの変換を行う
cwebp
コマンドファイル - ディレクトリ内の画像に
cwebp
コマンドを実行するシェルスクリプトファイル - Apacheに振り分けを指示する
.htaccess
ファイル
非常にシンプルで本番環境では厳しい部分も多々ありますが、小規模なサイトはこれで十分という場合もあると思います。
弊社のWebサイトやブログなど実際、小規模なので十分だったりします。…ということで実際に導入しました。
ChromeやSafariでアクセスしてください。デベロッパーコンソールで画像がWebPになっていることを確認できます。
https://www.ideamans.com/
成果などはまた別の記事で報告します。
WebP非対応のFirefoxではPNGやJpegが表示されます。
手順
では実際のWebサイトへの設定手順を説明します。前提は以下の通りです。
- SSHなどでシェルにログインできること
- Bashが使えること
- cronに定期実行コマンドを追加できること
1. cwebpコマンドをインストール
cwebp
コマンドはJpegやPNGファイルをWebP形式に変換するコマンドです。バイナリ形式でも配布されているので、ほとんどの環境でビルド不要のアップロードのみで利用できるはずです。
※ すでにcwebp
コマンドがインストールされていればこの手順は不要です。
こちらからお使いの環境に合わせたコンパイル済みのWebPコマンド群をダウンロードして、bin/cwebp
ファイルを任意のパスに配置します(例: /usr/local/bin/cwebp
)。
実際のダウンロードはこちらです。
https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html
2018年10月13日現在、最新1.0.0のLinux版がなぜかありませんでした。私は
rc3
を選択しました。
とりあえずバージョンを表示して実行できるか確認します。
$ /usr/local/bin/cwebp -version
1.0.0
2. 一括でWebPファイルを生成するスクリプト
次のBash向けのスクリプトを任意のパスに保存します(例: /home/me/webp.sh
)。
ディレクトリを再帰的にスキャンして、JpegとPNGにそれぞれ異なるオプションでcwebp
を実行、ただしWebPファイルが生成済みで元のファイルより新しい場合はスキップ、それだけのシンプルなスクリプトです。
ファイル名に半角スペースがある場合も考慮しています。
上部の変数宣言(特にDIR
)は、環境に合わせて書き換えてください。
※ findの記述を修正しました(10/16)
#!/bin/bash
DIR="./images" # 対象ディレクトリパス(要変更)
JPEG_CWEBP_OPTS="-q 75 -m 4" # Jpeg向け非可逆cwebpオプション
PNG_CWEBP_OPTS="-lossless" # PNG向け可逆cwebpオプション
CWEBP="/usr/local/bin/cwebp" # cwebpコマンドの場所
cd $(dirname $0)
shopt -s nocasematch
find $DIR -type f -regextype posix-extended -iregex ".*\.(jpe?g|png)$" -print0 | \
while IFS= read -r -d '' SRC; do
WEBP="$SRC.webp"
if [[ ! -e $WEBP || $SRC -nt $WEBP ]]; then
if [[ $SRC =~ \.jpe?g$ ]]; then
echo "Convert to lossy WebP: $SRC"
"$CWEBP" $JPEG_CWEBP_OPTS "$SRC" -o "$WEBP"
elif [[ $SRC =~ \.png$ ]]; then
echo "Convert to lossless WebP: $SRC"
"$CWEBP" $PNG_CWEBP_OPTS "$SRC" -o "$WEBP"
fi
fi
done
このスクリプトに実行権限を付与します。
$ chmod a+x /home/me/webp.sh
3. デバイスに応じてWebP画像を返す.htaccessファイル
画像専用ディレクトリのトップか、Apacheのドキュメントルートに以下の.htaccess
ファイルを設置します。
nginxでは使用できないので次節をご覧ください。
このファイルについては先日、詳しく記事を書きました。内容については、.htaccessによるWebPの選択的レスポンスとその問題点と改善案をご覧ください。
<IfModule mod_setenvif.c>
SetEnvIf Request_URI "\.(jpe?g|png)$" _image_request
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{SCRIPT_FILENAME}.webp -f
RewriteRule .(jpe?g|png)$ %{SCRIPT_FILENAME}.webp [T=image/webp]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=_image_request
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
すでに.htaccess
ファイルがある場合は上書きに気をつけてマージしてください。
4. cronに変換スクリプトを登録
定期的に変換スクリプトを実行します。例えば30分に1回実行する場合は次のように登録します。
*/30 * * * * /home/me/webp.sh
私は次のようにログファイルに出力するように登録しました。cwebp
の出力が標準エラーに対して行われるので、2>&1
もあった方がよいです。
*/30 * * * * /usr/local/bin/webp.sh >> /path/to/webp.log 2>&1
画像が追加・更新されてから実際にWebP画像が配信されるまで最長で30分のタイムラグがありますが、それまでは元のJpegまたはPNGが表示されます。
nginxの場合について
/etc/nginx/nginx.conf
などのシステム設定ファイルを編集する必要があります。
こちらの記事にnginxにおける方法をまとめたのでご参考ください。
IISの場合について
※ 10/15追記
IISもrewrite moduleという外部モジュールでURLの書き換えが可能なようです。
以下のページにXMLファイルの例がありました。
課題
大規模なサイトでの本番運用には以下のようにいろいろ課題がありますが、最低限のWebP対応方法として参考になれば幸いです。
- もしWebPの方がサイズが大きくなるなら変換しない方がいい
- 何%削減できたか成果がわからない
- エラーが発生してもわからないし、毎回それを繰り返す
- 30分で処理が終わらなかった場合の対処
- GIF対応(GIFをWebPに変換するコマンドもあり)
inotifyによるファイル変更検知の例
※ 10/15追記
Linuxにはinotifyと呼ばれるファイル変更検知の仕組みがあります。
その機能を使って、JpegファイルとPNGファイルが追加・変更されたら瞬時にWebPを作成する例がありました。
この方法であれば、WebP配信までのタイムラグがほとんどありません。