圖片Base64編碼

   引言  

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

 

   什麼是 base64 編碼?  

我不是來講概念的,直接切入正題,圖片的 base64 編碼就是可以將一副圖片數據編碼成一串字符串,使用該字符串代替圖像地址。

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

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

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

       

1

2

3

4

//在css裏的寫法

#fkbx-spch, #fkbx-hspch {
  background: url(data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=) no-repeat center;
}

 

1

2

//在html代碼img標籤裏的寫法

<img src="data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=">

 

上面分別是圖片的 base64 編碼在 css 裏面的寫法和在 html<img> 標籤裏的寫法。base64 編碼長得就是這個樣子,當然 base64 編碼不僅僅運用在圖片編碼,還可以:

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

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

 

   爲什麼要使用 Base64 編碼?  

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

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

所以,在這裏要明確使用 base64 的一個前提,那就是被 base64 編碼的圖片足夠尺寸小。以博客園的 logo 爲例:

如圖所示,博客園的 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 請求,這種轉換無疑更值得推崇。

 

   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 編碼,是不是很方便。

 

   一些誤區(2017.03.30更新)

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

 

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

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

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

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

通俗而言,就是圖片不會導致關鍵渲染路徑的阻塞,而轉化爲 Base64 的圖片大大增加了 CSS 文件的體積,CSS 文件的體積直接影響渲染,導致用戶會長時間注視空白屏幕。HTML 和 CSS 會阻塞渲染,而圖片不會。

 

2. 頁面解析 CSS 生成的 CSSOM 時間增加

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

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

CSSOM 生成過程:

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

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

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

 

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

最後,新開通的公衆號求關注,形式希望是更短的篇幅,質量更高一些的技巧類文章,包括但不侷限於 CSS:

image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章