Movable Type Advent Calendar 2021 - Adventar の記事投稿です。
12月18日に及川さんがこちらのプラグインを紹介していましたが、
WebP画像を自動生成する「WebPfy for Movable Type」 | 株式会社cherry-pick
この記事ではAWS版Movable Type限定ですが、10分程度で全自動WebP対応を実現するレシピを紹介します。
- 無料 Amazon Linux 2の機能のみにで実現できます。
- 従来フォーマットにも自動対応 ブラウザを判別してWebPか従来フォーマットか選択します。iOS13以下のiPhoneや旧ブラウザでも安心です。
作業手順
1. AWS版Movable Typeのセットアップ
こちらの記事などご参考ください。今回は nginxタイプを使用 しました。
Movable Type AMI版(AMI)スタートガイド| CMS プラットフォーム Movable Type を Amazon EC2 のクラウドで
とりあえずテスト用の画像ファイルをアップロードしておいてください。
2. webp-toolsのインストール
EC2インスタンスにSSHログインして、次のコマンドを実行します。
sudo yum install webp-tools
WebP変換のコマンドラインツールをインストールされます。
3. WebP変換バッチ
パスはどこでもよいので、次のシェルスクリプトを作成します。ここでは /home/ec2-user/webp.sh
としました。
#!/bin/bash
DIR="/data/file/static" # 対象ディレクトリパス(要変更)
SUDO="sudo -u www"
CWEBP="/usr/bin/cwebp" # cwebpコマンドの場所
JPEG_CWEBP_OPTS="-q 75 -metadata icc" # Jpeg向け非可逆cwebpオプション
PNG_CWEBP_OPTS="-lossless" # PNG向け可逆cwebpオプション
GIF2WEBP="/usr/bin/gif2webp" # gif2webpコマンドのパス
GIF2WEBP_OPTS="" # GIF向けgif2webpオプション
cd $(dirname $0)
shopt -s nocasematch
find $DIR -type f -regextype posix-extended -iregex ".*\.(jpe?g|png|gif)$" -print0 | \
while IFS= read -r -d '' SRC; do
WEBP="$SRC.webp"
if [[ ! -e $WEBP || $SRC -nt $WEBP ]]; then
echo "Convert $SRC to $WEBP"
if [[ $SRC =~ \.jpe?g$ ]]; then
$SUDO "$CWEBP" $JPEG_CWEBP_OPTS "$SRC" -o "$WEBP" 2>&1
elif [[ $SRC =~ \.png$ ]]; then
$SUDO "$CWEBP" $PNG_CWEBP_OPTS "$SRC" -o "$WEBP" 2>&1
elif [[ $SRC =~ \.gif$ ]]; then
$SUDO "$GIF2WEBP" $GIF2WEBP_OPTS "$SRC" -o "$WEBP" 2>&1
fi
echo
fi
done
このバッチファイルに実行可能なファイルパーミッションを与え、一度実行してみます。
chmod +x /home/ec2-user/webp.sh
/home/ec2-user/webp.sh
このバッチは、ドキュメントルートにあたる /data/file/static
以下の画像ファイル(拡張子.jpg
、.jpeg
、.png
、.gif
)をWebPに変換します。
例えば、 /data/file/static/image.jpg
は /data/file/static/image.jpg.webp
に変換するので、元のファイルも残ります(ブラウザに応じた出し分けは後ほど実装します)。
なんだか変換されたようなログが出力されたら成功です。
Convert /data/file/static/first/jpeg.jpg to /data/file/static/first/jpeg.jpg.webp
Saving file '/data/file/static/first/jpeg.jpg.webp'
File: /data/file/static/first/jpeg.jpg
Dimension: 240 x 214
Output: 3822 bytes Y-U-V-All-PSNR 41.38 44.12 41.57 41.77 dB
block count: intra4: 113
intra16: 97 (-> 46.19%)
skipped block: 68 (32.38%)
bytes used: header: 66 (1.7%)
mode-partition: 623 (16.3%)
Residuals bytes |segment 1|segment 2|segment 3|segment 4| total
macroblocks: | 2%| 26%| 32%| 38%| 210
quantizer: | 36 | 32 | 27 | 19 |
filter level: | 16 | 10 | 7 | 4 |
4. 出し分けの設定
nginx の設定ファイルを少しだけ変更します。
/etc/nginx/nginx.conf
40行目付近の、
server {
listen 80;
include /etc/nginx/nginx_common.conf;
}
この上に次のように設定を追記します。
# ここを追加
map $http_accept $webp_suffix {
default "";
"~*image/webp" ".webp";
}
server {
listen 80;
include /etc/nginx/nginx_common.conf;
}
/etc/nginx/nginx_common.conf
33行目付近の、
location / {
ssi on;
perl MTDynamicHandler::handler;
root /data/file/static;
limit_req zone=one burst=100;
}
の内部に次のように設定を追記します。
location / {
ssi on;
perl MTDynamicHandler::handler;
root /data/file/static;
limit_req zone=one burst=100;
# ここを追記
location ~* \.(png|jpe?g|gif)$ {
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
}
}
設定を変更したら nginx を再起動します。
sudo systemctl restart nginx
5. 動作確認
ブラウザで開発者ツールを開き、画像が含まれるページでNetwork
タブを確認します。
画像のType
がwebp
になっていれば、WebP対応は完了です。
6. 定期処理を登録
WebPへの変換バッチが定期的に実行されるよう、cronに登録します。
crontab -e
例えば次のように記述すると、WebP変換バッチが10分ごとに実行されます。
*/10 * * * * /home/ec2-user/webp.sh
注意点など
以上で画像をアップロードすると、それが10分以内にWebPに自動的に変換され、軽いファイルとして配信される仕組みができました。
お手軽な分、次のような注意点もあります。
- WebPの方がファイルが大きくなることも WebPは従来フォーマットより軽いことを保証するものではありません。特にGIFはWebPの方がファイルサイズが大きくなってしまうことがたまにあります。
-
非対応のファイルや拡張子ねじれ WebP自体、CMYKカラースペースには非対応ですし、拡張子
.png
なのに内容がJPEGといった変なファイルもたまにあります。 - 同じファイル名で上書きするとタイムラグが発生 更新日が変わると再度WebPへの変換が行われますが、定期処理が行われるまでWebPファイルは古い内容のままです。
- バッチの排他制御 もし大量のファイルが追加および更新され、10分で処理しきれない場合は大変なことになるかもしれません。
などなど、サイトによっては運用の品質に関わるところもあるでしょう。
有料のソリューションはこのあたり対処されていると思われます(少なくとも弊社では対応済み)。