繁體中文

開發者工具 · Base64 編碼器和解碼器

CSS 中的內嵌 Base64 圖片:何時 data: URI 有幫助,何時有害

· 為什麼它很重要

base64 效能

帶有內嵌 Base64 編碼的 SVG 圖示資料的 CSS 樣式表:URI
原始 ToolAcre 向量圖

將影像內聯為 Base64 資料:URI 會刪除請求,但會增加檔案並破壞快取。這篇文章列出了何時值得進行交易以及何時使用單獨的檔案更快。

成長到數百 KB 的樣式表 — 一個團隊的內聯習慣及其在載入時間中的表現

開發團隊決定將小圖示內聯為 Base64 資料:CSS 中的 URI 將減少 HTTP 請求並提高頁面載入速度。隨著時間的推移,隨著更多圖示的添加,樣式表成長到 400 千位元組。

CSS 套件本來應該包含樣式規則,但現在以圖片資料為主。團隊測量了載入時間,發現頁面比內聯之前更慢,而不是更快。問題變得清晰起來:400-kilobyte 樣式表在每個頁面加載時下載並緩存每個頁面,而如果圖標是單獨的檔案,則單個圖標檔案將被緩存並在每個頁面之間共享。

什麼資料:URI 內嵌以及為什麼它是 Base64 — 語法、媒體類型和大小損失

為網站新增更多頁面會使問題變得更糟,因為每個頁面都會再次下載包含所有內嵌影像的相同樣式表。這篇文章解釋了什麼是 data: URI、為什麼它是 Base64、內聯如何影響快取和效能,以及決定何時值得進行權衡的經驗法則。 data: 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 請求,因為資源已經存在並嵌入到父文件中。這可以節省一個或幾個 HTTP 請求,這在每個請求都有開銷的 HTTP/1.1 世界中很重要。

快取和關鍵路徑 - 為什麼每個包含樣式表的頁面都會再次下載內聯位元組

在 HTTP/2 或 HTTP/3 世界中,许多请求可以通过一个连接进行多路复用,因此节省的空间较小。 Base64 編碼的大小損失是直接且顯著的。当保存为 XML 文件时,SVG 图标为 3 千字节,当进行 Base64 编码并嵌入为数据:URI 时,该图标将变为 4 千字节。必須將因編碼而增加的 33% 大小新增至包含樣式表的每個頁面。如果在十页上使用该图标,则样式表将下载十次,每次都包含相同的 4 千字节编码图像。

如果圖示是一個單獨的檔案,則 3 KB 的原始檔案將下載一次並快取,然後在所有十個頁面上從快取中使用。對於大多數圖標來說,經濟選擇是顯而易見的:單獨的檔案總體上更小。只有當圖標僅在一頁或極少數頁面上使用且該圖標對該頁面確實至關重要時,內聯優勢才適用。每個頁面上都出現的圖示不太適合內聯;最好是作為單獨的快取檔案。

客戶端解析成本 — CSS 和 HTML 解析器處理多大的內聯字串,定性描述

僅在登陸頁面上使用的一次性插圖可能會受益於內聯以保存請求。快取抵消了內聯資料的大部分好處:樣式表中的 URI。樣式表通常會快取數天或數週。下載樣式表後,即使瀏覽器已經快取了該圖片,也會再次下載其中內嵌的每個資源。如果更新樣式表,即使只更改了一項 CSS 規則,也必須重新驗證或重新下載所有內聯資料。

這會導致膨脹:顏色或間距的變更會觸發樣式表的完全重新下載,包括未變更的千位元組影像資料。單獨的圖片檔案可以使用自己的過期標頭獨立快取、單獨更新並在樣式表和頁面之間重複使用。當資源是單獨的檔案時,瀏覽器快取的效率比資源嵌入到較大檔案中時要高效得多。當大型 Base64 字串嵌入到樣式表中時,解析和渲染成本會增加。 CSS 解析器在應用規則之前必須讀取整個樣式表。

工作範例:將一個小 SVG 圖示內聯為文字 — 將標記貼到編碼器中並手動組裝資料:URI

具有內聯 Base64 的 400 千字節樣式表是 400 千字節的文字,必須在應用任何規則之前對其進行解析。渲染具有大資料的頁面的 HTML 解析器:樣式屬性或背景圖片屬性中的 URI 必須解碼 Base64 並在元素渲染之前建構圖片。對於簡單的 SVG 圖示來說,這是微不足道的。對於更複雜的圖片或更大的圖標,解碼和渲染發生在主執行緒上,可能會阻塞互動性。定性成本是真實的,但如果不進行分析就很難衡量。

通常,如果內聯影像大於數千位元組,則單獨的檔案速度更快。一個有效的例子展示了確切的權衡。採用一個簡單的 SVG 箭頭圖標,1.2 千字節的 XML。 Base64 編碼後,它變成 1600 個字符,或大約 1.6 千字節,並帶有 data: URL 前綴。帶有背景圖片的單獨 CSS 規則: url(/icons/arrow.svg) 可能會在樣式表中新增 40 位元組。圖示檔案下載一次、快取並重複使用。內聯會為該圖示儲存一個 HTTP 請求,但會向每個樣式表載入 1.6 千位元組。

有效的經驗法則 — 小型、關鍵、一次性資產內聯;其他一切都作為檔案

如果樣式表為 50 千字節並在 20 頁面之間共享,則內聯該圖標會使每次站點訪問的總下載量增加 32 千字節。它節省的HTTP請求最多就是幾百位元組的開銷。此請求也會在 HTTP/2, 中自動重複使用,從而消除開銷差異。除非樣式表很小、圖示很大或圖示恰好出現在一頁上而不是其他地方,否則內聯交易會損失慘重。經得起審查的經驗法則是有限且具體的。

可以內聯微小的、關鍵的、一次性的資產。僅出現在一個不尋常頁面上的 200 位元組 SVG 箭頭可能會被內聯以節省請求開銷。其他一切都應該分開。關鍵渲染路徑邏輯很重要:如果圖示必須立即可見且每一毫秒的載入時間都會消耗轉換,那麼內聯可能會獲勝。對於具有典型圖示的典型頁面,單獨的檔案幾乎總是更好。使用您的實際資產測試這兩種方法,並測量頁面負載、快取命中率和請求瀑布。

這不包括什麼 - HTTP/2 和 HTTP/3 多路復用細節和圖片格式壓縮

不要假設內聯是一種無需測量的最佳化。導致樣式表臃腫的最簡單方法是增量內聯,而不測量每次添加是否實際上更快。 Base64 編碼器和解碼器可協助您在進行內聯之前做出此決定。將 SVG 標記或其他圖示來源作為文字貼上到工具中。點擊編碼並設定選項以產生資料:URI。該工具會向您顯示資料的準確長度:URL。將其與單獨的 CSS 規則和資源檔案本身的大小進行比較。

計算需要多少頁共享樣式表才能在內聯檔案與單獨檔案之間實現收支平衡。組裝 data: URI 並在將其提交到樣式表之前在實際的 HTML 頁面中進行測試。如果 URI 長於幾百個字符,則嵌入的成本可能大於保存請求的好處。使用該工具測試您的實際圖示和資源,然後測量內聯前後對實際頁面載入指標的影響。

重點:謹慎內聯並測量 — Base64 編碼器和解碼器如何讓您對 SVG 標記進行編碼並在提交之前查看確切的大小

高效能方法是對內嵌進行選擇性。每個頁面或多個頁面上使用的圖示是單獨的快取檔案。僅在一頁上使用的圖示或對首次繪製真正關鍵的圖示可以內聯。權衡您的實際資產和頁面,而不是遵循一般建議。在將任何內聯資源新增至樣式表之前,請使用 Base64 編碼器和解碼器查看其確切大小。尺寸損失是真實存在的,並在每次頁面瀏覽時都會成倍增加。

快取和請求多路復用使得內聯的原始好處不再那麼重要。對於大多數現代應用程式來說,較小的樣式表和來自單獨檔案的更好的快取效率超過了請求開銷。謹慎地內聯,衡量結果並信任衡量結果而不是直覺。