快速ページ表示のためのblank.gifのdata URI化、最短表現や処理の重さを実際にテストしてみた
今日は、Webページを素早く表示するために、lazyloadやスプライトで使うblank.gif画像をdata URI化する手法に関して。モダンブラウザで表示に問題のない最短文字数とデコード処理にかかる時間を調査してみました。ちょっと技術的です。
blank.gifというと、古い人には「スペーサーかよ!」と思われるかもしれませんが、今でも画像のlazyloadに使ったり、スプライト画像のベースに使ったりと、意外と使うものです。
このblank.gifを「data URI化」するとページ表示が早くなるんじゃないかと思い、調査したりテストしたりしてみました。結論としては、次のようなものでした。
- モダンブラウザで正しく表示されるblank.gifのdata URIは最短74文字の次の表現:
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- data URI化したblank.gifのデコード処理は1画像あたり45マイクロ秒~100マイクロ秒程度なので、よほど大量でなければdata URIのほうが高速
- おそらくほとんどの場合は、blank.gifを使うよりもdata URIを使うほうが高速に表示できる(ただし初回訪問のユーザーに対してのみ)
「data URIって何なの?」という方は、この記事の後半の解説を参照してください。data URIを使うときのメリットとデメリットもあわせて説明しています。
blank.gifのdata URI化、最も短い表現は?
1ピクセル×1ピクセルの透明画像をdata URI化するといっても、意外といろんなバリエーションがありました。最短は42文字、最長はPNG版の114文字でした。
また、data URIではありませんが画像のsrc属性に「//:0」や「file://null」などを指定するといった手法もありました。
それぞれ、各種ブラウザで正しく「1ピクセル四方の透明画像」として正しく表示するかを確認したところ、現行のモダンブラウザで正しく表示される最短data URIは74バイトでした。
ちなみに、IE 11を無視すれば、中身のないSVGが60バイトで最短でした。
テストしたdata URI文字列は次のとおりです
- 長さ:42バイト
data:image/gif;base64,R0lGODlhAQABAAAAACw=
- 長さ:54バイト
data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=
- 長さ:58バイト
data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=
- 長さ:60バイト (SVG)
data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'/>
- 長さ:74バイト
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- 長さ:78バイト
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
- 長さ:82バイト
data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==
- 長さ:82バイト
data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- 長さ:114バイト (PNG)
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=
- 長さ:4バイト(data URIではありませんが参考に)
//:0
- 長さ:11バイト(data URIではありませんが参考に)
file://null
data URIの処理は重い? SVGだとさらに重い?
blank.gifの最短data URI表現が見えてきました。しかし、data URIには根本的な問題があるとも言われています。それは、処理の重さです。
画像ファイルをURLから取得して読み込むのに比べて、data URIは文字列をBase64デコードして画像として読み込む必要があるため、data URIを使うと重くなるといいます。
確かに、大きな画像をモバイル端末のような比較的非力なコンピュータで処理するとそうかもしれません。でも、blank.gif程度の小さなサイズではどうでしょうか。
実際に実験してみたところ、1つのblank.gifのdata URI(82バイト長)をブラウザが読み取ってデコードして処理するのにかかる時間は平均で45マイクロ秒でした。
デコードはCPU速度に依存するため、半分の速度のCPUをエミュレートして試したところ、平均110マイクロ秒と倍以上の時間がかかりました
さて、1ページに同じ画像が複数回使われている場合、URL参照の場合はそのデータを1回取得すればいいだけですが、data URIの場合はすべての画像がデコード処理されます。では、1ページにblank.gifを何個使っていると、data URIのほうが遅くなるのでしょうか。
URLで参照して画像を取得するのにかかる時間を仮に100ミリ秒とすると、クライアントの端末が多少遅いとしても、使っているblank.gif画像が900個ほどまでならば、data URI化するほうが表示は早くなるという計算ですね。
また、IEを無視すれば最短なのはSVGでした(60バイト)。しかし、SVGの処理はGIFなどの画像と比べてさらに遅いとも言われます。では、空のSVG画像をblank.gifの代わりに使ってdata URI化して使うと、どれぐらい重くなるのでしょうか。
前述のdata URIの場合と同様の条件で計測してみたところ、1画像あたり必要な処理時間は48.9マイクロ秒でした。どうやら、1ピクセル四方の透明画像程度でしたら、SVGだから重いというのは、さほど気にする必要はなさそうです。
data URI化って何?
そもそも「data URI(データ・ユーアールアイ)」とは何かも説明しておきましょう。
わかりやすく言うと、こういうものです。
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
通常、Webページで使う画像では、src属性には「画像がある場所のURL」を指定しますよね。ブラウザは、そのURLに画像データを取りに行って表示するわけです。
でも、Webページの表示にかかる時間をできるだけ短くするには、ブラウザがWebサーバーと通信する回数を減らすのが大切です。
そこで、「画像がある場所のURL」ではなく、「画像データそのもの」をHTML内に書けるようにできるのがdata URIというものなのです。
前出のdata URI例を分解してみると、次のような作りになっています。
- 最初の「data:」は、これがdata URIであることを示すdataプロトコル指定
- 次の「image/gif」は、指定する内容がGIF画像であることを示すMIMEタイプ
- セミコロンで区切ったあとの「base64」は、画像データそのものをHTML内にテキストで記述するためにBase64でエンコード(文字列化)していることを示す指定
- カンマで区切ったあとに、画像データ自体をBase64エンコードしたテキストを記述
自分でdata URIを作るのは面倒ですが、元画像をアップロードすれば自動的にdata URIにしてくれるサービスもありますので、実はさほど手間がかかるものではありません(私はdata: URI Generatorを使うことが多いです)。
data URIを使う際には、次のようなメリットとデメリットがあることを理解するのが大切です。
[メリット]そのリソース(画像など)のためにブラウザが追加でHTTPリクエスト(サーバーとの通信)をする必要がなくなる。これにより、ページの内容をすべて表示するまでにかかる時間を短縮できる。
[デメリット]同じ画像を1ページ内で複数回使っているときに、注意が必要。URLで画像を指定する場合は、その画像のためのサーバーとの通信は1ページに1回で済む。しかし、data URIを使っている場合は、すべての画像のdata URIをブラウザが読み込んでデコード(文字列から画像データに変換)する必要がある。
[デメリット]1ページ内に同じ画像を複数回参照している際に、HTTPリクエスト本数の節約のためにdata URI化するならば、すべてをdata URI化しなければ意味がない。1つでもURLでの参照が残っていると逆効果になる。
[デメリット]画像をBase64で文字列化すると、必要なデータ転送量はバイナリ(通常の画像ファイル)の場合と比べて1.3倍以上になる。
[デメリット]data URIはリモート画像ファイルと違ってブラウザにキャッシュされない。そのため、再訪問ユーザーでも毎回ページを訪れるたびに読み込みと処理が必要。
[デメリット]HTMLを見てもわかりづらい。
こう書くと、デメリットのほうが多く見えますね。でも、この記事で解説しているように、うまく使えばWebページの表示を高速化できる手法です。
特に、初回訪問のユーザーが多いサイトでは、特徴を理解して、うまく使いたいものですね。
ソーシャルもやってます!