概要
Google
のChrome
ブラウザではウェブページの性能を測るためLighthouse
と言う機能を提供してます。この機能を使うとウェブページの全般的な性能を確認することができるし、次のように問題点も確認ができます。

今回のブログポストではウェブページでイメージフォーマットを最適化してServe images in next-gen formats
の問題を解決してイメージのlazy loading
でDefer offscreen images
の問題を解決する方法について説明します。
avifとwebpフォーマット
Serve images in next-gen formats
の問題を解決するためにはavif
フォーマットまたはwebp
フォーマットのイメージを提供する必要があります。avif
とwebp
フォーマットのイメージはIE
以外のモーダンブラウザは大体サポートしてるイメージフォーマットです。
Pythonでavifとwebpフォーマットイメージ生成
今回のブログポストではjpg
やpng
フォーマットのイメージファイルをPython
を使ってavif
とwebp
フォーマットのイメージを生成する方法について説明します。
Python
を使ってavif
やwebp
フォーマットのイメージを生成するためにはPillow
とpillow-avif-plugin
ライブラリをインストールする必要があります。次のコマンドを使ってPillow
とpillow-avif-plugin
のライブラリをインストールします。
pip install Pillow pillow-avif-plugin
Pillow
はPython
でイメージを扱う時使うライブラリで、pillow-avif-plugin
はPillow
ライブラリを使ってイメージのフォーマットを変更する時、avif
フォーマットで保存できるようにするライブラリです。
- Pillow: https://pypi.org/project/Pillow/
- pillow-avif-plugin: https://pypi.org/project/pillow-avif-plugin/
ライブラリをインストールしたら、optimization_images.py
ファイルを生成して次のように修正します。
import os
import glob
from PIL import Image
import pillow_avif
target_folder = './assets'
files = glob.glob(f'{target_folder}/**/*.jpg', recursive=True) + glob.glob(f'{target_folder}/**/*.png', recursive=True)
for f in files:
print(f)
title, ext = os.path.splitext(f)
webp_file = title + '.webp'
avif_file = title + '.avif'
if os.path.isfile(webp_file) == False:
img = Image.open(f)
img.save(webp_file, format='webp')
img.close()
if os.path.isfile(avif_file) == False:
img = Image.open(f)
img.save(avif_file, format='AVIF' )
img.close()
ソースコードを詳しくみてみましょう。
私はイメージファイルをassets
フォルダに保存して管理してます。もし、イメージファイルを他のフォルダで保存してる場合、下記の部分を修正してください。
...
target_folder = './assets'
...
イメージを保存したフォルダ中で全てのjpg
とpng
フォーマットファイルを探します。
...
files = glob.glob(f'{target_folder}/**/*.jpg', recursive=True) + glob.glob(f'{target_folder}/**/*.png', recursive=True)
...
その後、全てのファイルを回しながらファイルフォーマットを変更します。ファイルフォーマットを変更したあtフォーマットに合わせてファイル名も変更するためos.path
を使ってファイル名を準備しました。
...
for f in files:
title, ext = os.path.splitext(f)
webp_file = title + '.webp'
avif_file = title + '.avif'
...
そしたら、webp
フォーマットのファイルが存在してるか確認して、存在しない場合は、既存ファイルをwebp
フォーマットで変更して保存します。
...
for f in files:
...
if os.path.isfile(webp_file) == False:
img = Image.open(f)
img.save(webp_file, format='webp')
img.close()
...
同じに、avif
ファーマットのファイルが存在するか確認して、存在しない場合、既存のファイルをavif
フォーマットで変更して保存します。
...
for f in files:
...
if os.path.isfile(avif_file) == False:
img = Image.open(f)
img.save(avif_file, format='AVIF' )
img.close()
これでjpg
またはpng
フォーマットのイメージファイルをavif
とwebp
フォーマットで変更するPython
スクリプトを作ってみました。
avifとwebpファイル生成
そしたら、このように作ったoptimization_images.py
ファイルを実行してavif
とwebp
フォーマットファイルを生成して身まあしょう。avif
とwebp
フォーマットあいお生成するため次のコマンドを使ってPython
スクリプトを実行します。
python optimization_images.py
そしたら次のようにイメージファイルリストが確認できるし、avif
とwebp
フォーマットのファイルが生成されることが確認できます。
...
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_new_data_with_no_data.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_pull_to_refresh.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_no_data.png
./assets/images/category/flutter/2023/RefreshIndicator/listview.png
./assets/images/category/flutter/2023/RefreshIndicator/refreshindicator_refresh_no_data.png
./assets/images/category/flutter/2023/find_child_and_parent_widget/basic_app.png
pictureとsourceタグ
次は、このように生成したavif
とwebp
フォーマットファイルをウェブページで使う方法について説明します。ウェブページで色んなフォーマットのイメージを使うためには<picture />
タグと<source />
タグを使う必要があります。イメージをロードする部分を、次のように<picture />
タグと<source />
タグを使ってavif
とwebp
フォーマットをロードするように修正します。
<picture>
<source srcset="example.avif" type="image/avif" />
<source srcset="example.webp" type="image/webp" />
<img src="example.png" alt="example file" />
</picture>
このように<picture />
と<source />
タグを使うと、ブラウザがサポートするフォーマットのイメージをダウンロードして表示されるようになります。
loading lazy
Lighthouse
を使ってイメージが多いウェブページを検査すると、Defer offscreen images
の問題が出ることが確認できます。この問題を解決するためには<img />
タグに次のようにloading="lazy"
を追加します。
<picture>
<source srcset="example.avif" type="image/avif" />
<source srcset="example.webp" type="image/webp" />
<img src="example.png" alt="example file" loading="lazy" />
</picture>
loading lazy
について詳しい内容は下記のリンクで確認できます。
- Lazy loading: https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading#images_and_iframes
完了
これでウェブページの性能を上げるため新しいイメージフォーマットであるavif
とwebp
ファイルを生成して、<picture />
と<srouce />
タグを使ってイメージをローディングして最適化する方法についてみてみました。また、loading="lazy"
を使ってイメージロードを最適化する方法についてもみてみました。
Lighthouse
でよく発生する指摘事項なので、今回よく覚えておくと役に立つと思います。もし、ブラウザではなくローカルやCI
環境でLighthouse
を実行する方法を確認したい方は下記のリンクを参考してください。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。