画像をBase64で変換して埋め込めば、HTTPリクエストがなくなり高速表示できる

よこのじ(@yokonoji_work)です。

Base64という仕組みを利用すると、画像をテキストデータとしてhtmlコードに埋め込むことができます。これにより、画像を読み込む際のHTTPリクエストとそのレスポンスがなくなるのでWebページの表示が速くなります。そんなBase64を詳しく見てみたいと思います。

Base64とは?

64文字(A~Z, a~z, 0~9, +, /)を用いて、これら文字以外のデータを扱うための仕組みがBase64です。例えば、電子メールは仕組み上、文字という限られたデータしか扱えないようです。しかし、Base64で画像などのデータをテキストデータに変換すれば、電子メールでも画像の送受信をすることができます。

それでは、詳しい仕組みを確認してみます。

次のようにBase64では、あるデータを6ビットごとに区切ります。6ビットですから、2の6乗=64です。つまり、6ビットに区切ったデータはA~Z, a~z, 0~9, +, /のどれかに当てはめることができます。例えば、010010はS、000110はGといった感じです。

095-image-base64-Base64の仕組み

Cover Story: Understanding Base64 Encoding

データは0か1の数字の集まりです。つまり、あらゆるデータをA~Z, a~z, 0~9, +, /の文字の並びで表すことができます。あとは、Base64でエンコードされたデータを受け取った側がSは010010、Gは000110のように逆の処理(デコード)を行えば元のデータに復元できます。

Base64はデータサイズが増える

Base64は限られたデータしか扱えない環境で、他のデータも扱うことができる素晴らしい仕組みです。しかし、デメリットもあります。

それは、Base64でエンコードするとデータサイズが30%~40%増加するということです。

Base64は元のデータを6ビットごとに区切って、その6ビットを64文字のいずれかに置き換えているのでした。A~Z, a~z, 0~9, +, / は、1文字=1バイト=8ビットです。つまり、6ビットを8ビットに置き換えています。

8ビット/6ビット=1.33

計算すると、Base64でエンコードするだけで33%もデータサイズが増加するのが分かります。また、MIME:Multipurpose Internet Mail Extension(多目的インターネットメール拡張)においては、76文字ごとに改行(=2バイト)が入るようです。これも考慮すると、Base64を利用することでデータサイズは37%も増加します。

Base64エンコード後の1文字は、元のデータの6ビットを表現しているので、Base64エンコード後が76文字ということは、元のデータは、76 × 6ビット = 456ビット = 57バイトである。57バイトを76 + 2 = 78バイトで表現しているので、データ量は78 ÷ 57 ≒ 1.37 = 137%となる。

Wikipedia Base64

Base64でWebページの表示を高速化

データサイズが大きくなるBase64ですが、画像をBase64でエンコードしてhtmlコードに埋め込むことで、Webページの表示を速くすることができます。

この仕組みは単純です。

Webページを構成するcssファイルや画像は、そのデータを読み込むたびにブラウザとサーバー間でHTTPリクエストとレスポンスの通信が発生します。

095-image-base64

こちらは「よこのじ.work」にアクセスして、「Windowsで文字起こし(テープ起こし)の自動化!writer.app?Googleドキュメント?」のアイキャッチ画像を読み込んだ時の処理時間です。リクエスト送信に1.56ms(Request sent)、サーバーから応答があったのが622.57ms後(Waiting(TTFB))、そして画像のダウンロードに523.98ms(Content Download)かかっています。元データは424KBで、アイキャッチ画像のサイズでは46.3KBです。

処理時間は画像サイズやサーバーの能力、ネットワークの速度などに影響されますが、こうしてみてみると、HTTPリクエストとレスポンスであるRequest sentとWaiting(TTFB)は無視できない時間と言えます(私のサイトでは画像サイズが最適化されていないのが丸わかりです、、)。

さて、Base64を利用すれば、画像をテキストデータとしてhtmlコードに埋め込めるのでした。もうお分かりかと思いますが、テキストデータとして埋め込まれていれば、それをそのままデコードすれば画像データが得られます。つまり、画像データを読み込むためにHTTPレスポンスを送り、サーバーからの応答を待つという時間がなくなります。

このように、無駄な通信処理がなくなることはWebページの表示の高速化につながります。

しかし、Base64の扱いには注意が必要です。データサイズが37%も増加するのでダウンロードにかかる時間は増加するからです。そのため、データサイズの小さな画像に対してのみBase64を使うのが一般的です。

元のデータサイズが小さい場合は、データサイズ増加によるダウンロード時間の増加よりも、リクエストとレスポンスの時間を削減する方が効果が大きいが、データサイズが大きい場合は、削減したリクエストとレスポンスの時間以上にダウンロード時間が増加する可能性があるからです。どこが逆転の境目となるのかは、サーバーの能力やネットワークの速度による部分があるのではっきりしないのが難しいところです(数MBという大きなサイズでない限り、リクエストとレスポンスを削減する方が効果があるというのが、おおよその目安のようです)。

インラインイメージBase64でサイト速度高速化!画像最適化テクニック!!

Base64を使う方法

Base64で画像を表示させるには、次のような記述を行います。

通常:<img src="imagename.png" />
Base64:<img src="data:image/png;base64,******" />

*****の部分にBase64でエンコードしたコードを記述します。pngの部分はデータ形式に応じてjpegやgifに変更してください。

画像のエンコードは次のサイトで行うことができます。

Syncer Base64エンコーダー

また、Google Chromeで画像を開いて、デベロッパーツール(F12)のSourcesよりエンコード結果を得ることもできます。

095-image-base64-chromeでエンコード

エンコード結果の長い文字列をテキストエディターに記述すると動作が重くなるかと思います。そのため、設計段階では通常の画像表示をさせておき、公開前にBase64での表示に変えるのが良いかと思います。

キャッシュを利用するためにCSSに書くべき

htmlファイルは通常キャッシュさせませんので、htmlファイルに<img src=”data:image/png;base64,******” />のように記述すると、アクセスのたびに37%増加したデータをダウンロードすることになってしまいます。

このような無駄を避けるために、backgroundプロパティを使ってcssファイルに記述するべきです。

.sample {
  background: url("data:image/png;base64,*****");
}

このようにしておけば、Base64によりHTTPリクエストとレスポンスをなくしながらも、cssファイルのキャッシュも利用できるので、初回訪問者に対してもリピーターに対しても高速なWebページ表示を提供できます。