天天看點

【前端攻略】:玩轉圖檔Base64編碼

   引言  

圖檔處理在前端工作中可謂占據了很重要的一壁江山。而圖檔的 base64 編碼可能相對一些人而言比較陌生,本文不是從純技術的角度去讨論圖檔的 base64 編碼。标題略大,不過隻是希望通過一些淺顯的論述,讓你知道什麼是圖檔的 base64 編碼,為什麼我們要用它,我們如何使用并且友善的使用它,并讓你懂得如何去在前端的實際工作中運用它。

   什麼是 base64 編碼?  

我不是來講概念的,直接切入正題,圖檔的 base64 編碼就是可以将一副圖檔資料編碼成一串字元串,使用該字元串代替圖像位址。

這樣做有什麼意義呢?我們知道,我們所看到的網頁上的每一個圖檔,都是需要消耗一個 http 請求下載下傳而來的(所有才有了 csssprites 技術的應運而生,但是 csssprites 有自身的局限性,下文會提到)。

沒錯,不管如何,圖檔的下載下傳始終都要向伺服器送出請求,要是圖檔的下載下傳不用向伺服器送出請求,而可以随着 HTML 的下載下傳同時下載下傳到本地那就太好了,而 base64 正好能解決這個問題。

那麼圖檔的 base64 編碼長什麼樣子呢?舉個栗子。www.google.com 的首頁搜尋框右側的搜尋小圖示使用的就是base64編碼。我們可以看到:

【前端攻略】:玩轉圖檔Base64編碼
【前端攻略】:玩轉圖檔Base64編碼

上面分别是圖檔的 base64 編碼在 css 裡面的寫法和在 html<img> 标簽裡的寫法。base64 編碼長得就是這個樣子,當然 base64 編碼不僅僅運用在圖檔編碼,還可以:

thunder://QUFodHRwOi8vZG93bi5zYW5kYWkubmV0L3RodW5kZXI3L1RodW5kZXI3LjEuNS4yMTUyLmV4ZVpa(不要複制我我真的不是種子)

嘿嘿沒錯,迅雷的“專用位址”也是用 Base64 加密的,有興趣自行 google,不做贅述。

   為什麼要使用 Base64 編碼?  

那麼為什麼要使用 base64 傳輸圖檔檔案?上文也有提及,因為這樣可以節省一個 http 請求。圖檔的 base64 編碼可以算是前端優化的一環。效益雖小,但卻缺能積少成多。

說到這裡,不得不提的是 CssSprites 技術,後者也是為了減少 http 請求,而将頁面中許多細小的圖檔合并為一張大圖。那麼圖檔的 base64 編碼和 CssSprites 有什麼異同,又該如何取舍呢?

是以,在這裡要明确使用 base64 的一個前提,那就是被 base64 編碼的圖檔足夠尺寸小。以部落格園的 logo 為例:

【前端攻略】:玩轉圖檔Base64編碼

如圖所示,部落格園的 Logo 隻有 3.27KB,已經很小了,但是如果将其制作轉化成 base64 編碼,生成的 base64 字元串編碼足足有 4406 個,也就是說,圖檔被編碼之後,生成的字元串編碼大小一般而言都會比原檔案稍大一些。即便 base64 編碼能夠被 gzip 壓縮,壓縮率能達到 50% 以上,想象一下,一個元素的 css 樣式編寫居然超過了 2000個 字元,那對 css 整體的可讀性将會造成十分大的影響,代碼的備援使得在此使用 base64 編碼将得不償失。

那麼,是不是表示 base64 編碼無用武之地呢?不然。當頁面中的圖檔滿足以下要求,base64 就能大顯生手。

如果圖檔足夠小且因為用處的特殊性無法被制作成雪碧圖(CssSprites),在整個網站的複用性很高且基本不會被更新。

那麼此時使用 base64 編碼傳輸圖檔就可謂好鋼用在刀刃上,思前想後,符合這個規則的,有一個是我們經常會遇到的,就是頁面的背景圖 background-image 。在很多地方,我們會制作一個很小的圖檔大概是幾px*幾px,然後平鋪它頁面當背景圖。因為是背景圖的緣故,是以無法将它放入雪碧圖,而它卻存在網站的很多頁面,這種圖檔往往隻有幾十位元組,卻需要一個 http 請求,十分不值得。那麼此時将它轉化為 base64 編碼,何樂而不為?

下面是一個隻有 50 位元組的2*2的的背景圖。将其轉化成 base64 編碼,隻有 100 多個字元,相比一個 http 請求,這種轉換無疑更值得推崇。

【前端攻略】:玩轉圖檔Base64編碼

   CssSprites與Base64編碼  

簡單陳述一下我對何時這使用這兩種優化方法的看法。

使用CssSprites合并為一張大圖:

頁面具有多種風格,需要換膚功能,可使用CssSprites

網站已經趨于完美,不會再三天兩頭的改動(例如button大小、顔色等)

使用時無需重複圖形内容

沒有 Base64 編碼成本,降低圖檔更新的維護難度。(但注意 Sprites 同時修改 css 和圖檔某些時候可能造成負擔)

不會增加 CSS 檔案體積

使用base64直接把圖檔編碼成字元串寫入CSS檔案:

無額外請求

對于極小或者極簡單圖檔

可像單獨圖檔一樣使用,比如背景圖檔重複使用等

沒有跨域問題,無需考慮緩存、檔案頭或者cookies問題  

   更便捷的将圖檔轉化為Base64編碼  

将圖檔轉化為 base64 編碼有許多工具,例如本文中我所使用的 http://www.pjhome.net/web/html5/encodeDataUrl.htm ,但是很多這些網站是國外網站,經常被牆登陸不了。這裡介紹一個更為快捷的方法,就是利用 Chrome 浏覽器(我想 FEer 都應該有Chrome 浏覽器吧=。=)。

在 chrome 下建立一個視窗,然後把要轉化的圖檔直接拖入浏覽器,打開控制台,點 Source,如下圖所示,點選圖檔,右側就會顯示該圖檔的 base64 編碼,是不是很友善。

【前端攻略】:玩轉圖檔Base64編碼

Base64 雖有優點,但是缺點也很明顯,在使用上存在一些明顯的缺陷。

1. 使用 Base64 不代表性能優化

是的,使用 Base64 的好處是能夠減少一個圖檔的 HTTP 請求,然而,與之同時付出的代價則是 CSS 檔案體積的增大。

而 CSS 檔案體積的增大意味着什麼呢?意味着 CRP 的阻塞。

CRP(Critical Rendering Path,關鍵渲染路徑):當浏覽器從伺服器接收到一個HTML頁面的請求時,到螢幕上渲染出來要經過很多個步驟。浏覽器完成這一系列的運作,或者說渲染出來我們常常稱之為“關鍵渲染路徑”。

通俗而言,就是圖檔不會導緻關鍵渲染路徑的阻塞,而轉化為 Base64 的圖檔大大增加了 CSS 檔案的體積,CSS 檔案的體積直接影響渲染,導緻使用者會長時間注視空白螢幕。HTML 和 CSS 會阻塞渲染,而圖檔不會。

Base64 跟 CSS 混在一起,大大增加了浏覽器需要解析CSS樹的耗時。其實解析CSS樹的過程是很快的,一般在幾十微妙到幾毫秒之間。

CSS 對象模型 (CSSOM):CSSOM是一個建立在web頁面上的 CSS 樣式的映射,它和DOM類似,但是隻針對CSS而不是HTML。

CSSOM 生成過程:

【前端攻略】:玩轉圖檔Base64編碼

CSSOM 生成過程大緻是,解析 HTML ,在文檔的 head 部分遇到了一個 link 标記,該标記引用一個外部 CSS 樣式表,下載下傳該樣式表後根據上述過程生成 CSSOM 樹。 這裡我們要知道的是,CSSOM 阻止任何東西渲染,(意味着在CSS沒處理好之前所有東西都不會展示),而如果CSS檔案中混入了Base64,那麼(因為檔案體積的大幅增長)解析時間會增長到十倍以上。

而且,最重要的是,增加的解析時間全部都在關鍵渲染路徑上。

是以,當我們需要使用到 Base64 技術的時,一定要意識到上述的問題,有取舍的進行使用。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

繼續閱讀