画像の最適化について

フロントエンドエンジニア8ヶ月目の者です。
業務を進めていく上で、画像を圧縮したり、適切なフォーマットを選んだりする重要性を学びました。
そこで、今回は、画像の最適化について自身の勉強も含めて書けていけたらと思います。
##なぜ画像を最適化させる必要があるのか
そもそもなぜ画像を最適化させる必要があるのでしょうか。
それは、**画像がWebページのパフォーマンスに大きく影響する**からです。
画像はHTMLやCSSと比べてもファイルサイズが大きくなりがちです。
そうすると、どうしても画像を読み込むのに時間がかかってしまい、Webページのパフォーマンスに悪影響を及ぼします。
逆に言えば、**画像次第でWebページのパフォーマンスは改善可能**だということです。
では、この画像の読み込み速度を上げるために私たちができることは何なのでしょうか？

## 適切な画像フォーマットを選択する
まず、考えるべきことは適切な画像フォーマットを選択することです。
では、どういった場合にどの画像フォーマットを利用すれば良いのでしょうか？

### JPEG
JPEGは**圧縮率が高く、フルカラーの画像を扱える**ので**写真**などの画像に用いると良いでしょう。
ただ、JPEGを使用する場合は圧縮率と画質に気をつける必要があります。
圧縮率を上げれば画像を軽くできますが、その分画質が落ちてしまいます。
そのため、JPEGを使用する際にはどこまで画質を落として、画像を軽くするのかといったことを考える必要があるでしょう。

### PNG
PNGは8bitと24bitの2種類あり、8bitでは256色、24bitではフルカラーで写真を保存でき、透過させられるのも特徴です。
PNGはJPEGとは違って可逆性圧縮を採用しているため、**圧縮したデータを完全に復元**できます。
しかし、その分データ容量が大きくなってしまうので気を付けましょう。
PNGの使い道は**イラストやロゴ**です。
イラストやロゴはJPEGだと圧縮時のノイズが目立ちますが、PNGでは綺麗に書き出せるでしょう。

### SVG
SVGは**ベクター形式**で表現された画像で、ラスター形式のPNGやJPEGと違い、**拡大縮小で劣化することがない**ことが特徴です。
また、CSSやJavaScriptでアニメーションを制御できるのも特徴として挙げられるでしょう。
SVGの使い道としては、**単純な形のオブジェクト**を表現するのに向いています。
しかし、写真等の複雑な画像の表現には向いていないので気を付けましょう。

### GIF
GIFは256色以下の画像を扱うことができ、画像フォーマットの中では歴史が長いようです。
GIFは**アニメーション**で使うことが多いです。
ただ、**GIFアニメーションは重くなってしまいがち**なので、軽くするために工夫する必要があります。

### WebP
WebPはGoogleがオープンソースで開発している、新しい画像フォーマットです。
WebPは**圧縮率が高いにもかかわらず、画質を担保している**のが特徴として挙げられます。
Googleの発表によると、PNGと比べ約26%、JPEGでは約25〜34%も容量を圧縮できるようです。
（ソース：[A new image format for the Web](https://developers.google.com/speed/webp)）
しかし、WebPは**一部対応していないブラウザが存在する**ので注意しましょう。
![can i use.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/add0b5dd-6fae-66bc-0890-dd0dad380a07.png)
(引用：[Can I use](https://caniuse.com/webp))

## 画像を圧縮する

適切に画像を圧縮することも重要です。
画像の圧縮を行ってくれるツールがこの世には存在するので、それを使いましょう！
私は**ImageOptim**（Macのみ）をいつも使用しています。
![ImageOptim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/1fa43d13-1804-9c20-d401-7dcc4414b5a8.png)
(引用：[ImageOptim](https://imageoptim.com/howto.html))

画像を使用する際には圧縮ツールに通すことを癖付けると良いかもしれません。
ちなみに、私はこんな感じで**Finderのツールバー**にImageOptimをセットしています。
![finder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/d36522c0-a8e8-6ab4-bca2-82f2d978822d.png)

## 画質を落とす
画質を落とすことで、画像を軽くできます。
私はいつも**Photoshop**で画質を調整しています。
画質を落としすぎて見栄えが悪くなってしまったら、元も子もないので見栄えが悪くならない程度に画質を落としていきます。

 **ファイル>書き出し>Web用に保存**の手順でクリックすると下記の画面が出てきます。
![photoshop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/33b9b903-9a9b-7232-b582-e2f874eb5680.png)
この画面で右上にある**画質の項目を0-100で変更できる**ので、見栄えが悪くならない程度に画質を落とします。
画像によって適切な画質が異なりますが、70くらいがちょうど良いでしょう。
もちろん、もっと下げられることもあるので、画像の見栄えを確認しながら画質を調整してみてください。

## GIFアニメーションを動画にする
GIFアニメーションはどうしても重くなってしまいます。
そのため、時にはGIFアニメーションを動画にした方が軽い！ということもあります。
### サイト内に動画にできるGIFアニメーションがあるか調べる
まずは、サイトの中に動画に変換できるGIFがあるかどうか確認しましょう。
この作業は**Lighthouse**を使用することでできます。

1. デベロッパーツールを開く
2. Lighthouseタブをクリック
3. Performanceチェックボックスにチェックを入れる
4. Generate reportをクリック

上記の手順でopportunitiesのところに下記のようにGIFアニメーションを動画に置き換えたときの計測結果が出てきます。
![gif.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/35057391-6424-a19e-8eb2-6e712dcb690b.png)
###GIFを動画に変換する

世の中便利で、GIFアニメーションを動画にするためのツールも用意されています。
英語のサイトにはなりますが、[こちら](https://web.dev/replace-gifs-with-videos/)でGIFアニメーションをMP4にする方法が紹介されています。

## WebPを使う
軽量なWebPを使うのも一つの手です。
ただ、非対応のブラウザのためにフォールバックを用意する必要があります。
現在（2021/12/22）非対応のブラウザの中で気をつけるべきなのが下記です。

1. IE 全てのバージョン
2. MacOs Catalina以前のバージョン
3. iOS 13以前 

（引用：[そろそろWebPに切り替えよう。変換方法や対応ブラウザ、使い方を解説！](https://webdesign-trends.net/entry/13745)）

現状はまだまだ**フォールバックが必要な状態**と言えますが、時間の経過につれて非対応ブラウザのシェアも少なくなってくるので、いつか非対応ブラウザを気にすることなく使用できる時が来るでしょう。

### フォールバックの準備
フォールバックには`picture`タグを使います。

```HAML
<picture>
  <source srcset="Webpのパス" type="image/webp">
  <img src="フォールバックのパス">
</picture>
```

上記のように記述することで非対応のブラウザでは、フォールバックの画像が表示されます。

### Webpに変換する
Webpにはツールを使って変換できます。
有名なのは**Squoosh**じゃないかなっと思います。![squoosh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/24bbd5d3-e499-8648-c826-54ffdaf5781e.png)
(引用： [Squoosh](https://squoosh.app/))
SquooshはWebpの変換にも使えますが、画像の圧縮にも対応しています。



## パターンがあるものはリピートさせる
背景画像に多いですが、画像には一定のパターンが存在するものがありますよね。
そういった場合には、画像全体を書き出すのではなくパターンの最小サイズを書き出して、それをリピートさせることで画像サイズを抑えることができます。
`background`プロパティ（[MDN](https://developer.mozilla.org/ja/docs/Web/CSS/background)）で画像のパスとリピート処理を一括で指定できます。


## 画像を遅延読み込みさせる
こちらは画像の最適化というよりも、**ファーストビューを高速化させる**ための方法です。
画像を遅延で読み込みさせると、画像を最初に読み込まない分ファーストビューが高速化されます。
私がよく使用するのは**lazysizes.js**です。
下記のようにclassにlazyloadを設定して、data-srcに遅延表示させたい画像へのパスを設定するだけです。

```HAML
<img class="lazyload" src="低品質画像のパス" data-src="遅延表示させたい画像のパス">
```

詳しい使い方は[こちら](https://github.com/aFarkas/lazysizes)を参考にしてください。

## CDNを使う
現在は、CDNから画像を配信することがスタンダードらしいです。
CDNから画像を配信することによって、**40%から80%のファイル削減効果**があります。（ソース：[Use image CDNs to optimize images](https://web.dev/image-cdns/)）
下記の画像のようにフォーマットや画質までURLを変更することで指定できます。
![imageCDN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269914/a3d440a0-fe41-a5d2-c3d8-0d8122f1d013.png)
（引用：[Use image CDNs to optimize images](https://web.dev/image-cdns/)）
そして、画像配信用のCDNには**Self-managed image CDN**と**Third-party image CDN**の2種類存在します。
### Self-managed image CDN
Self-managed image CDNは自分たちでインフラを管理することに抵抗がない人に最適な方法です。
ただ、商用のCDNよりも機能が少なくドキュメントも限定的です。
無料で使えるものでは、**[Thumbor](https://github.com/thumbor/thumbor)**が代表として挙げられます。
### Third-party image CDN
Third-party image CDNは画像専用のCDNをサービスとして提供しているものです。
こちらは導入が簡単で10-15分ほどで完了します。
Third-party image CDNは**有料で使用量に応じて費用がかかる**ことが多いです。
そのため、予算と相談してどのサービスを使用するか決めましょう。

## まとめ
今回は色々調べながら、画像の最適化について書かせていただきました。
状況によっては今回紹介したことが使えないことがあるかと思いますが、参考になると幸いです。
最後まで読んでいただきありがとうございました。

## 参考サイト
- [An image format for the Web](https://developers.google.com/speed/webp)
[画像最適化によるパフォーマンス改善](https://murashun.jp/article/performance/image-optimisation.html)
- [【JPEG・GIF・PNG】画像ファイル形式の基礎・特徴と適切な扱い方まとめ](https://liginc.co.jp/web/design/material/50037#:~:text=JPEG%EF%BC%88Joint%20Photographic%20Experts%20Group,%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E5%A4%9A%E3%81%84%E3%81%A7%E3%81%99%E3%80%82)
- [これが完全版！レスポンシブ対応のwebp画像を実装するHTMLのコード](https://coliss.com/articles/build-websites/operation/work/how-to-use-webp-images-in-html.html)
- [Optimize your images](https://web.dev/fast/#optimize-your-images)
- [【Photoshopで画像を軽くする方法】ファイルの容量が重い！リサイズの方法は？](https://core-canvas.com/photoshop-8-1070)
- [lazysizes](https://github.com/aFarkas/lazysizes)
- [そろそろWebPに切り替えよう。変換方法や対応ブラウザ、使い方を解説！](https://webdesign-trends.net/entry/13745)