URI:統(tǒng)一資源標識符。由一個‘協(xié)議’和‘定位符’組成。定位符其實是補充信息,它可以是一個地址(如果是這樣的話,那這個URI就是一個URL),也可以是數(shù)據(jù)本身(比如 data URI),或者命名空間(URN).
URI較URL是一個更廣的概念,或者說URL是最常見的一種URI。所以Data URI不是URL。
RFC 2397(The "data" URL scheme)中第一次定義了Data URI:
它允許文檔直接使用一小段數(shù)據(jù)作為"即時數(shù)據(jù)",而不是之前那樣必須引用外部資源
隨后,文檔定義了data URI的格式:
data:[<mediatype>][;base64],<data>
在這種格式中,data:就是URI的協(xié)議,表明就是一個data URI。
mediatype可能是image/png之類的,如果不填,默認是text/plain
我們一般指定base64編碼方式,如果不填,默認是低效的URL編碼。
對于非英文字符串,URL編碼是一種非常浪費空間的編碼方式。URL編碼在地址欄中很常見,對于URL安全的字符(比如英文字母、數(shù)字、中劃線、下劃線等)就直接顯示,對于URL不安全的字符(比如非英文的字符)就編碼成%XX的形式。
二進制文件中包含很多URL不安全的字符,所以轉(zhuǎn)成URL編碼字符之后很冗長。因此所以有了base64編碼。(關(guān)于base64編碼http://www.lxweimin.com/writer#/notebooks/3331706/notes/11322163)。
通過對比 Base64編碼明顯比URL編碼小很多(但是因為使用了6個比特而不是8個比特,所以仍然比壓縮過的二進制文件大一些)
因此,當我們提到data URI時,99%同時是指配套使用base64編碼技術(shù),來把一個二進制資源文件(比如字體或圖片)合并到主文檔(可能是HTML,可能是CSS)中。
性能神器還是棄之可惜的雞肋?
誤區(qū)一:節(jié)省請求等于性能優(yōu)化?
對于前端來說,顯而易見好處是能夠減少圖片的HTTP請求,而缺點可能是不夠顯而易見。
樣式表會變得很大,從而阻塞關(guān)鍵下載和渲染。
通俗地講,圖片文件或字體文件的體積轉(zhuǎn)移到了HTML或CSS中,而后者的體積直接影響到渲染,導致用戶會長時間注視空白屏幕。HTML和CSS阻塞渲染,圖片不會。
這是Base64的第一個缺點,資源合并到CSS文件中導致體積增大,進而阻塞關(guān)鍵路徑。
誤區(qū)二:Base64 能獲益于Gzip壓縮?
Gzip是在web前端最常見的一種壓縮文本的方法。
Gzip壓縮算法分兩步。
第一步:采用LZ77算法的一種變種替換字符串。
第二步:使用Huffman樹來儲存出現(xiàn)的位置和長度。
簡單來講,Gzip把原文本中多次出現(xiàn)的相同字符串標記為一個‘標記’,所以文本中重復出現(xiàn)的字符串越多,壓縮率越高。
圖片經(jīng)過Base64轉(zhuǎn)化后變成的文本是無規(guī)律的,所以在Gzip中不能達到較高的壓縮率。
誤區(qū)三:考慮緩存了嗎?
Base64影響了我們的緩存策略。
我們把樣式、圖片、字體文件等合并到一起之后,整個變成一個資源,我們無法再分別為它們配置緩存時間,以及更新資源。而圖片、字體、HTML和CSS的更新頻率都是不一樣的。
在平常的項目中,CSS文件的修改頻率是較高的,圖片其次,而字體文件幾乎不改,我們一般會為不同類型的文件設置不同的緩存失效時間,以及在更新某個文件之后單獨更新這個文件的時間戳。混在一起之后,即使我們只是想更新CSS規(guī)則里面的一個字號,整個幾百k的文件就會重新生成。用戶不得不在每次小型更新后重新下載整個大文件,這違背了基本的緩存原則。
Base64跟CSS混在一起,難以分別進行緩存設置和更新。
誤區(qū)四:CSSOM渲染
Base64跟CSS混在一起,大大增加了瀏覽器需要解析CSS樹的耗時。一般解析CSS樹的過程是很快的,一般在幾十微秒到幾毫秒之間。如果CSS文件中混入了Base64,那么(因為文件體積的大幅增長)解析時間會增長到十倍以上。增加的解析時間全部都在關(guān)鍵渲染路徑上
有沒有適合使用data URI的場景?
有!在某些罕見特例中,也許使用Base64是合理的選擇。在規(guī)避了以上缺點時,就可以考慮使用它了。