開発者ツール · Base64 エンコーダーおよびデコーダー
CSS 内のインライン Base64 画像: データ: URI が役立つ場合と有害な場合
· なぜそれが重要なのか
base64 パフォーマンス
画像を Base64 データとしてインライン化する: URI はリクエストを削除しますが、ファイルが大きくなり、キャッシュが無効になります。この記事では、取引に価値がある場合と、別のファイルを使用した方が速い場合について説明します。
数百キロバイトにまで増大したスタイルシート — あるチームのインライン化の習慣と、それが読み込みタイミングにどのように現れたか
開発チームは、CSS 内の小さいアイコンを Base64 データ (URI) としてインライン化すると、HTTP リクエストが減少し、ページの読み込み速度が向上すると判断しました。時間の経過とともにアイコンが追加されるにつれて、スタイルシートは 400 キロバイトまで増加しました。
CSS バンドルにはスタイル ルールが含まれているはずですが、現在は画像データが大半を占めています。チームが読み込みタイミングを測定したところ、ページはインライン化前よりも速くなったのではなく、遅くなったことがわかりました。問題は明らかになりました。400 キロバイトのスタイルシートは、ページが読み込まれるたびにダウンロードされ、ページごとにキャッシュされますが、アイコンが個別のファイルである場合、単一のアイコン ファイルがキャッシュされ、すべてのページで共有されます。
データとは: URI インライン化とそれが Base64 である理由 - 構文、メディア タイプ、サイズ ペナルティ
サイトにさらにページを追加すると、各ページがすべてのインライン画像を含む同じスタイルシートを再度ダウンロードするため、問題はさらに悪化しました。この投稿では、データ (URI とは何か)、URI が Base64 である理由、インライン化がキャッシュとパフォーマンスにどのような影響を与えるか、いつトレードオフに値するかを判断するための経験則について説明します。データ: URL は、外部ファイルにリンクするのではなく、リソースを HTML または CSS ファイルに直接埋め込む方法です。構文は data:mediaType;base64,encoded_bytes です。
mediaType は、SVG の場合は image/svg+xml、PNG の場合は image/png、テキストの場合は text/plain など、その後にどのような種類のリソースが続くかを宣言します。 ;base64 フラグは、ペイロードがパーセント エンコードされたテキストではなく、Base64 エンコードされたテキストであることを示します。 encoded_bytes は実際のデータです。ブラウザーは、href、src、またはbackground-imageプロパティでdata: URLを検出すると、Base64をデコードし、リソースをインラインでレンダリングします。リソースはすでに存在し、親ドキュメントに埋め込まれているため、HTTP リクエストは発生しません。これにより、1 つまたはいくつかの HTTP リクエストが節約されます。これは、各リクエストにオーバーヘッドがある HTTP/1.1 の世界では重要です。
キャッシュとクリティカル パス — スタイルシートを含むすべてのページでインライン化されたバイトが再度ダウンロードされる理由
多くのリクエストを 1 つの接続上で多重化できる HTTP/2 または HTTP/3 の世界では、節約効果はさらに小さくなります。 Base64 エンコードのサイズペナルティは即時かつ重大です。 XML ファイルとして保存すると 3 キロバイトとなる SVG アイコンは、Base64 でエンコードされてデータとして埋め込まれると 4 キロバイトになります: URI。エンコードによる 33% のサイズ増加を、スタイルシートを含むすべてのページに追加する必要があります。アイコンが 10 ページで使用されている場合、スタイルシートは 10 回ダウンロードされ、毎回同じ 4 キロバイトのエンコードされた画像が含まれます。
アイコンが別個のファイルである場合、3 キロバイトのオリジナルは一度ダウンロードされてキャッシュされ、その後 10 ページすべてでキャッシュから使用されます。ほとんどのアイコンでは、経済的な選択が明確です。個別のファイルは全体的に小さくなります。インライン化の利点は、アイコンが 1 ページまたはごく少数のページで使用され、アイコンがそのページにとって本当に重要である場合にのみ適用されます。すべてのページに表示されるファビコンは、インライン化の候補としては適していません。別個のキャッシュ ファイルとして使用する方が適切です。
クライアントでの解析コスト — CSS および HTML パーサーによってどのくらい大きなインライン文字列が処理されるか (定性的に説明)
ランディング ページでのみ使用される 1 回限りのイラストは、リクエストを保存するためにインライン化すると便利な場合があります。キャッシュは、データのインライン化、つまりスタイルシート内の URI の利点のほとんどを無効にします。スタイルシートは通常、数日または数週間キャッシュされます。スタイルシートがダウンロードされると、ブラウザーにその画像が既にキャッシュされている場合でも、そのスタイルシートにインライン化されているすべてのリソースが再度ダウンロードされます。スタイルシートが更新された場合は、CSS ルールが 1 つだけ変更された場合でも、すべてのインライン データを再検証または再ダウンロードする必要があります。
これにより肥大化が発生します。色や間隔を変更すると、変更されなかった数キロバイトの画像データを含むスタイルシートの完全な再ダウンロードがトリガーされます。個別の画像ファイルは、独自の有効期限ヘッダーを使用して個別にキャッシュされ、個別に更新され、スタイルシートやページ間で再利用できます。ブラウザーのキャッシュは、リソースが大きなドキュメントに埋め込まれている場合よりも、別個のファイルである場合の方がはるかに効率的です。大きな Base64 文字列がスタイルシートに埋め込まれている場合、解析とレンダリングのコストはさらに増大します。 CSS パーサーは、ルールを適用する前にスタイルシート全体を読み取る必要があります。
作業例: 小さな SVG アイコンをテキストとしてインライン化 — マークアップをエンコーダーに貼り付け、データを組み立てる: URI を手動で
インライン Base64 の 400 キロバイトのスタイルシートは、ルールを適用する前に解析する必要がある 400 キロバイトのテキストです。大きなデータを含むページをレンダリングする HTML パーサー: style 属性または background-image プロパティの URI は、要素をレンダリングする前に Base64 をデコードして画像を構築する必要があります。単純な SVG アイコンの場合、これは簡単です。より複雑な画像や大きなアイコンの場合、デコードとレンダリングがメインスレッドで行われるため、インタラクティブ性がブロックされる可能性があります。定性的なコストは実際のものですが、プロファイリングなしで測定するのは困難です。
原則として、インライン画像が数キロバイトより大きい場合は、別のファイルを使用した方が高速です。実際の例では、正確なトレードオフが示されています。シンプルな SVG 矢印アイコン、1.2 キロバイトの XML を考えてみましょう。 Base64 でエンコードすると、1600 文字、つまり data: URL プレフィックスが付いた約 1.6 キロバイトになります。背景画像を使用した別の CSS ルール: url(/icons/arrow.svg) は、おそらく 40 バイトをスタイルシートに追加します。アイコン ファイルは一度ダウンロードされ、キャッシュされて再利用されます。インライン化により、その 1 つのアイコンに対する HTTP リクエストが 1 つ節約されますが、スタイルシートの読み込みごとに 1.6 キロバイトが追加されます。
有効な経験則 — 小さく、重要な、使い捨てのアセットをインラインで使用します。それ以外はすべてファイルとして
スタイルシートが 50 キロバイトで、20 ページ間で共有されている場合、そのアイコンをインライン化すると、サイト訪問ごとに合計ダウンロード量が 32 キロバイト増加します。保存される HTTP リクエストは、最大でも数百バイトのオーバーヘッドです。リクエストは HTTP/2, にも自動的に多重化されるため、オーバーヘッドの差がなくなります。スタイルシートが小さいか、アイコンが巨大であるか、アイコンが 1 ページにのみ表示され、他の場所には表示されない限り、インライン化トレードは大きく損をします。精査を経ても生き残る経験則は限定的かつ具体的です。
小規模で重要な、使い捨てのアセットをインライン化できます。 1 つの異常なページにのみ表示される 200 バイトの SVG 矢印は、リクエストのオーバーヘッドを節約するためにインライン化される場合があります。それ以外はすべて別々にする必要があります。クリティカルなレンダリング パス ロジックが重要です。アイコンをすぐに表示する必要があり、読み込み時間のミリ秒ごとに変換コストがかかる場合は、インライン化が勝つ可能性があります。一般的なアイコンを含む一般的なページの場合は、ほとんどの場合、別個のファイルの方が適しています。実際のアセットを使用して両方のアプローチをテストし、ページ負荷、キャッシュ ヒット率、リクエスト ウォーターフォールを測定します。
これでカバーされないもの — HTTP/2 および HTTP/3 多重化の詳細と画像形式の圧縮
インライン化が測定のない最適化であると想定しないでください。スタイルシートが肥大化する最も簡単な方法は、各追加が実際に高速になるかどうかを測定せずに、段階的にインライン化することです。 Base64 エンコーダとデコーダは、インライン化をコミットする前にこの決定を行うのに役立ちます。 SVG マークアップまたはその他のアイコン ソースをテキストとしてツールに貼り付けます。 [エンコード] をクリックし、データ URI を生成するオプションを設定します。このツールは、データの正確な長さ (URL) を表示します。これを、別の CSS ルールおよびアセット ファイル自体のサイズと比較してください。
インライン展開と個別のファイルの損益を均衡させるために、スタイルシートを共有する必要があるページ数を計算します。 data: URI を組み立て、スタイルシートにコミットする前に実際の HTML ページでテストします。 URI が数百文字を超える場合、埋め込みのコストがリクエストを保存するメリットよりも高くなる可能性があります。このツールを使用して実際のアイコンとアセットをテストし、インライン化の前後で実際のページ読み込みメトリクスへの影響を測定します。
要点: インライン化は控えめにして測定 — Base64 エンコーダーとデコーダーを使用して SVG マークアップをエンコードし、コミット前に正確なサイズを確認する方法
パフォーマンスの高いアプローチは、インライン化を選択することです。すべてのページまたは多くのページで使用されるアイコンは、個別のキャッシュ ファイルです。 1 ページだけで使用されるアイコン、または最初のペイントに非常に重要なアイコンをインライン化できます。一般的なアドバイスに従うのではなく、実際のアセットとページのトレードオフを測定してください。 Base64 エンコーダとデコーダを使用して、インライン化されたアセットをスタイルシートに追加する前にその正確なサイズを確認します。サイズペナルティは実際に発生し、ページビューごとに増加します。
キャッシュとリクエストの多重化により、インライン化の本来の利点はそれほど重要ではなくなりました。ほとんどの最新のアプリケーションでは、より小さなスタイルシートと個別のファイルからのキャッシュ効率の向上がリクエストのオーバーヘッドを上回ります。インライン化は控えめに行い、結果を測定し、直感よりも測定値を信頼します。