相信無論是前端還是后端開發工程師,對于Base64都不會感到陌生,在開發中我們經常會將一些小圖片以Base64的形式存儲和加載。然而知其然也要知其所以然,Base64究竟是什么,我們為什么要使用Base64,以及Base64的優缺點又是什么呢?今天我們就來聊一聊。
什么是Base64
首先Base64是一種編碼格式,普遍應用于需要在網絡中存儲和傳輸的二進制數據。為什么叫Base64呢,主要是因為這種編碼格式每個字節的前兩位只能是0,剩下只有6位可以表示,所以對于Base64來說,一個字節只能表示64種情況。Base64的名字由此而來。
為什么要存在Base64
但我們不難發現,這樣的話這種編碼格式并不能充分利用存儲資源,是比較低效的,那為什么還要用Base64這種編碼呢?為什么不直接傳輸二進制而要轉成Base64格式再去傳輸呢?
原因是因為base64最早是用在郵件傳輸協議中的,當時郵件傳輸協議只支持ascii字符傳遞,ascii碼可以用來表示所有的英文字符和數字還有一些符號,但其中還存在很多不可見字符或者叫控制字符,不可見字符在傳輸過程中可能會產生一些錯誤,如果郵件中只傳輸英文數字等,那么ascii是可以直接支持不會有問題,但是如果你要在文件中傳輸一些二進制文件,圖片,視頻等資源的時候,不可避免的轉成ascii的時候會出現非英文數字的情況,也就是上面所說的不可見字符,這時就有可能會導致傳輸過程中出現問題。
Base64就是用來解決這個問題的,人們想到把二進制劃分為多個3個字節的塊,把每3個字節(24位)轉換成4個6位,每個六位根據查表對應一個ASCII符號。如下圖所示:
上圖是Base64的編碼字典
如上圖所示,比如我們有一個3個字節的數據,轉成ascii碼以后就是第一行所示,但我們查詢ascii碼會發現第三個字節是個不可見字符,所以如果在曾經的郵件傳輸協議中這么傳輸可能會在過程中產生一些錯誤,于是我們需要轉成base64再去傳輸,根據Base64的轉化規則曾經的三個字節就變成了4組6位的值,然后我們需要在每一組前面補充兩個0補齊字節長度。于是根據Base64編碼之后我們打印出的結果就是S3qb這個字符串。
另外這個例子比較特殊,我們正好是個3字節數據,如果1個字節或者2個字節時,我們就會發現位數不能正好被6整除,不能整除就會是下面這個示例展示的樣子
如何編碼和解碼Base64
在 JAVAScript 中,有兩個函數被分別用來處理解碼和編碼 base64 字符串。
- btoa() — 字符串轉 Base64編碼
- atob() — 通過Base64規則解碼成ascii字符串
使用Base64存儲和加載圖片好不好?
相信大家對于Base64的編解碼和原理已經有了深入了解,最后我們簡單聊聊在前端頁面中使用Base64加載圖片到底好不好。所有事情都有兩面性,沒有絕對的好不好,只有在某些特定場景下合不合適。我們來看看Base64加載圖片的優劣點:
資源大?。焊鶕覀兩厦嫣岬降脑恚覀兒苋菀装l現Base64會比正常資源要大三分之一,Gzip壓縮之后差距會縮小。
緩存方式:圖片資源很好緩存,但如果是base64的話,如果是在cssjs中引入可以跟文件一起進行緩存,如果在html中直接引用則必須緩存html文件,所以緩存方便程度上肯定是圖片資源文件更方便緩存。
加載方式:html/css中引入base64會導致文件體積變大,從而導致首屏展示的比較慢,而用過圖片資源方式異步引入會首屏會展示的比較快。但對于需要加載很多圖片的情況下,尤其是腳在很多小圖片小icon的情況下,如果不使用雪碧圖的方式就會造成請求量很大,在http1.1/1.0協議下,在不開啟keep-alive的情況下,會導致效率低下重復創建銷毀連接通道,并且瀏覽器存在請求線程限制,并且存在網絡io延遲,這種情況下base64效率更高,但如果你的應用使用http2/3的協議,base64的優勢就不大了。
結語
所以綜合來看Base64加載圖片的方式多數情況下并不是最優選擇,只有在圖片比較小,比較獨立并不適合做成雪碧圖的情況下再去使用比較好。