そろそろ、Webページの最適化もした方がいいかなと思い始め、試しに以下のURLからアクセスできる Google の「PageSpeed
Insights」というWebサイトのサービスを使って、このブログのトップページの読み込み速度を評価してみました。
https://developers.google.com/speed/pagespeed/insights/
結果はPC版のスコアが 88、モバイル版のスコアが 42 でした。
PC版は十分そうですが、モバイル版が遅い判定を受けているので、やっぱり何とかしないとと思い、改善可能な項目に目を向けてみました。
画像フォーマットを変えれば 9 s も短縮できるとのことです。確かに画像はかなり適当に用意していたので改善の効果は期待できそうでした。
guetzli を使ってみる
最初に提案のあった JPEG XR 形式(.jxr)を試してみようとしましたが、ちょっと調べて情報が少なかったのでとっつきにくそうな感じがありました。一旦別のアプローチを試してみることにしました。
Google 製の JPEG エンコーダーである guetzli があるとのことで、試してみることにしました。以下のURLから実行ファイルをダウンロードできます。
https://github.com/google/guetzli/releases
ヘルプを見てみるとオプションは少なく、使い方もとても簡単でした。
Guetzli JPEG compressor. Usage:
guetzli [flags] input_filename output_filename
Flags:
--verbose - Print a verbose trace of all attempts to standard output.
--quality Q - Visual quality to aim for, expressed as a JPEG quality value.
--memlimit M - Memory limit in MB. Guetzli will fail if unable to stay under
the limit. Default is 6000 MB
--nomemlimit - Do not limit memory usage.
基本的には以下のように --quality のみを設定すればOKというシンプルさ。
guetzli_windows_x86-64.exe --quality 84 input.jpg output.jpg
早速試しに実行してみました。そしたら、ものすごく処理時間がかかる..1枚変換するだけで何十秒も待たされます。Mayaでオフラインレンダリングしてい るのを待っている感覚です。
調べてみるとどうやら何回もエンコードを繰り返し、最適な設定を見つけてくれるため、処理時間がやたらかかってしまうようでした。まぁ圧縮率が高くて質のい い設定が自動で決まるなら文句はないですが、使えるシチュエーションは限られてきそうです。
WebP 形式を使ってみる
Google が開発したという画像フォーマット WebP 形式も試してみました。以下のページより、cwebp.exe というコマンドラインエンコーダーが含まれたプリビルド済み libwebp パッケージをダウンロードできます。
https://developers.google.com/speed/webp/download?hl=ja
ここでダウンロードしたパッケージを解凍すると、binの中に cwebp.exe
が入っているのが確認できると思います。こちらもヘルプを見てみると基本的な使い方は非常にシンプルです。
Usage:
cwebp [options] -q quality input.png -o output.webp
where quality is between 0 (poor) to 100 (very good).
Typical value is around 80.
詳細オプションも一応確認してみます。
Usage:
cwebp [-preset <...>] [options] in_file [-o out_file]
If input size (-s) for an image is not specified, it is
assumed to be a PNG, JPEG, TIFF or WebP file.
Windows builds can take as input any of the files handled by WIC.
Options:
-h / -help ............ short help
-H / -longhelp ........ long help
-q ............. quality factor (0:small..100:big)
-alpha_q ......... transparency-compression quality (0..100)
-preset ....... preset setting, one of:
default, photo, picture,
drawing, icon, text
-preset must come first, as it overwrites other parameters
-m ............... compression method (0=fast, 6=slowest)
-segments ........ number of segments to use (1..4)
-size ............ target size (in bytes)
-psnr .......... target PSNR (in dB. typically: 42)
-s ......... input size (width x height) for YUV
-sns ............. spatial noise shaping (0:off, 100:max)
-f ............... filter strength (0=off..100)
-sharpness ....... filter sharpness (0:most .. 7:least sharp)
-strong ................ use strong filter instead of simple (default)
-nostrong .............. use simple filter instead of strong
-partition_limit . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-pass ............ analysis pass number (1..10)
-crop .. crop picture with the given rectangle
-resize ........ resize picture (after any cropping)
-mt .................... use multi-threading if available
-low_memory ............ reduce memory usage (slower encoding)
-map ............. print map of extra info
-print_psnr ............ prints averaged PSNR distortion
-print_ssim ............ prints averaged SSIM distortion
-print_lsim ............ prints local-similarity distortion
-d .......... dump the compressed output (PGM file)
-alpha_method .... transparency-compression method (0..1)
-alpha_filter . predictive filtering for alpha plane,
one of: none, fast (default) or best
-alpha_cleanup ......... clean RGB values in transparent area
-blend_alpha ..... blend colors against background color
expressed as RGB values written in
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly
-hint ......... specify image characteristics hint,
one of: photo, picture or graph
-metadata ..... comma separated list of metadata to
copy from the input to the output if present.
Valid values: all, none (default), exif, icc, xmp
-short ................. condense printed message
-quiet ................. don't print anything
-version ............... print version number and exit
-noasm ................. disable all assembly optimizations
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
Experimental Options:
-jpeg_like ............. roughly match expected JPEG size
-af .................... auto-adjust filter strength
-pre ............. pre-processing filter
圧縮設定以外にも、画像のクロップとか透明ピクセルのフィルとか、ちょっとした画像処理オプションもあります。今回はとりあえずシンプルに quality のみを設定したいと思います。
quality は 84 で変換をいくつかの画像に試してみました。変換時間はかなり高速で、そして品質も高い。データサイズも Guetzli で変換したJPEGの半分くらいでした。アルファチャンネルも維持されつつ、データサイズもかなり削れて、これはかなり有能なフォーマットではないかという印象でした。
そして、テンションが上がってしまった私はサイト上の画像を次々に .webp に変換してアップロードして喜んでいたんですが、Chrome 以外で、例えば iPhone から Safari 経由で確認してみると画像が表示されなくなっている、という事態に。
調べてみるとAppleとMicrosoft系のブラウザは現状では未対応という状況でした。急いで巻き戻しました。
折角優秀なフォーマットなのにEdgeとSafariが壊滅というのは使いにくい..
最終的にJPEGとWebPのハイブリッドに落ち着く
最終的には以下のように<picture>要素を使って .webp が使えるブラウザでは WebPで表示、対応してないブラウザでは JPEG で表示というハイブリッド方式に落ち着きました。
<picture>
<source type='image/webp' srcset='hoge.webp'>
<img src='hoge.jpg' />
</picture>
結局ブラウザが Safari だったらファイルサイズ的には今までと大きくは変わらないですが、Chrome
の方は画像サイズが大分小さくなるので改善されることを期待。
改めてページ読み込み速度を評価してみる
主要な画像のフォーマットを WebP に置き換えて再度評価してみると..
ん?ほとんど変わらない?
確かに一部の画像しか置き換えていないのですが、主要な画像は置き換えましたし、この時点でもう少し変化がないと他の画像を置き換えたところで、ちょっと改 善の期待は薄いです。実は画像ではなく、Java Scriptとか別の部分がボトルネックになっている気配が。
もう少し詳細を確認しつつ、真のボトルネックは何なのか、何とか評価値をあげられないか粘ってみたいと思います。