`<img src="data:image/png;base64,iVBORw0...">` のようなコードを見たことがあるでしょう。画像ファイルを別に置かず、その中身を文字に変換して文書の中に丸ごと入れたものです。便利そうに見えますが、どこにでも使うとページはかえって遅くなります。
何と何を引き換えにしているか
Base64はバイナリ3バイトを4文字で表します。そのため結果は元より**約33%長くなります。**この損を受け入れて得られるのは「ファイルを別にリクエストしなくてよい」という一点だけです。この取引が得かどうかは、画像の大きさと登場回数で決まります。
| ファイルとして置く場合 | Base64で埋め込む場合 | |
|---|---|---|
| 転送量 | 元のサイズ | 約1.33倍 |
| リクエスト数 | 画像ごとに1回 | 0回(文書に含まれる) |
| ブラウザキャッシュ | 画像単位で再利用 | 不可 — 文書と一緒に毎回届く |
| 文書サイズ | 変わらない | 画像の分だけ大きくなる |
| 差し替え | ファイルを置き換えるだけ | 文書を直して配信し直す |
キャッシュを失うのがいちばん痛い
表の中で実際にいちばん効くのはキャッシュです。ファイルなら一度受け取れば次のページで再利用されますが、文書の中に文字として埋まっていると、ページを開くたびにその塊が一緒に届きます。ロゴをBase64にしてページが20枚あれば、利用者は同じロゴを20回受け取ることになります。
CSSに入れるともう少し微妙です。CSSファイルは通常よくキャッシュされるので画像も一緒にキャッシュされますが、代わりに**CSSを受け取り終わるまでページが描画されません。**重い画像をCSSに埋め込むと、初回表示が遅れます。
得になる場合
- **数KB以下の小さなアイコン** — リクエストを1つ節約する得が33%の損を上回ります。
- **外部ファイルを参照できない場所** — メール署名、1ファイルで配る HTML 文書、オフラインのレポート。
- **表示の遅れが目立つ場所** — 背景パターンのように、後から現れると気づかれるごく小さな画像。
- **ビルド成果物にファイルを足しにくいとき** — 設定1行で済ませたい一時的な資産。
損になる場合
- **写真** — 数百KBが1.33倍になり、キャッシュも効きません。ほぼ常にファイルのほうが有利です。
- **複数ページで繰り返される画像** — ロゴやヘッダー背景こそキャッシュの効果が最大の対象です。
- **頻繁に変わる画像** — 変えるたびに文書を直して配信し直すことになります。
- **アイコンが多数あるとき** — インラインSVGやスプライトのほうが適しています。
小さなアイコンならまずSVGを見る
単純なアイコンなら、PNGをBase64にするよりSVGのコードをそのまま入れるほうがたいてい短くなります。SVGはすでに文字の形式なので33%の損がなく、色をCSSから変えられ、どの解像度でもくっきりします。Base64が必要になるのは、たいていSVGでは表せない絵のときです。
変換はブラウザの中で完結するため、画像がサーバーに送られることはありません。逆方向、つまり受け取ったdata URI文字列を画像ファイルに戻すことも同じ場所でできます — ログやAPIレスポンスに埋まった文字列が何の絵なのかを確かめるときに役立ちます。