Blob URL (createObjectURL) と Base64 Data URL の性能比較とメモリ管理
JavaScript Frontend Performance WebAPI
結論
画像プレビュー等には URL.createObjectURL() を使い、表示後に URL.revokeObjectURL() で解放します。
// MDN公式仕様:Blob URL の生成と安全なメモリ解放
function previewImage(file) {
const objectUrl = URL.createObjectURL(file);
const img = document.createElement('img');
img.src = objectUrl;
img.onload = () => {
// ⭕ 描画完了後、メモリ参照を明示的に開放(メモリリーク防止)
URL.revokeObjectURL(objectUrl);
};
document.body.appendChild(img);
}
MDN公式仕様:2つの手法の性能比較マトリクス
| 評価軸 | Blob URL (createObjectURL) | Base64 Data URL (readAsDataURL) |
|---|---|---|
| 文字列のサイズ | 非常に短い短縮ポインタ URL | 元データより約 33% 肥大化 |
| 生成パフォーマンス | 超高速 (ポインタ生成のみ 0ms) | × CPU負荷の高いテキスト変換処理が必要 |
| メモリ解放 | URL.revokeObjectURL() の明示が必要 | ガベージコレクションで自動解放 |
| Service Worker | ❌ Service Worker内では使用不可 | ◯ 文字列として透過処理可能 |
実際に起こる事故:URL.revokeObjectURL() 忘れによるタブクラッシュ
MDN公式ドキュメント(URL.createObjectURL)で警告されている通り、生成された Blob URL は、明示的に URL.revokeObjectURL() が呼び出されない限り、ページが閉じられる(アンロード)までブラウザの内部メモリ内にデータを維持し続けます。
画像アップロードや動的CSVダウンロードが頻繁に行われるSPA(Single Page Application)において、revoke 漏れの Blob URL を生成し続けると、ブラウザのメモリ(RAM)が数GBまで膨れ上がり、スマートフォンやスペックの低い端末でタブがクラッシュ(OOM)する障害 が発生します。
メモリリーク防止の手順
<img src={url} />や<a>タグのダウンロード生成時にURL.createObjectURL(blob)を使用するimg.onloadまたは React のuseEffectクリーンアップ関数内でURL.revokeObjectURL(url)を呼び出す- 数KB以下の極小アイコンやインライン埋め込み以外で Base64 文字列を使用しない