由於 Arial, Verdana, Garamond or Times New Roman 這些字體幾乎在全部電腦上都有安裝,因此之前每一個網站都使用他們來渲染文本。至今,雖然webfonts已經在互聯網中獲得廣泛的使用,可是咱們依然不知道如何高效的加載他們。css
爲了提供更好的用戶體驗,我寫了一些怎麼作才能高效加載webfonts的簡單解決方法,這個方案的實施並不須要昂貴的硬件支持。html
主要從如下方案進行介紹:web
(1)使用woff字體格式(PS:多是EOT和TTF格式默認狀況下不會進行壓縮,然而WOFF格式具備內建壓縮,並且WOFF格式的支持很普遍的緣由。);瀏覽器
(2)對於不支持webfonts的瀏覽器使用「web安全」字體(PS:使用前言中提到的一些幾乎全部電腦都安裝了的字體做爲後備字體,保證用戶可以正常瀏覽網頁);緩存
(3)下載字體的「二進制」格式,而且優化它;安全
(4)使用你本身的字體庫;網絡
(5)將字體進行base64編碼後,存放於CSS文件中;app
(6)若是用戶本地沒有網頁請求的字體,那麼就異步加載該字體,而且將該字體存儲在localStorage中,以便第二次請求字體直接從localStorage中進行讀取,避免字體加載帶來的性能問題;異步
英文版本的做者 2014/10/09 更新內容web安全
若是你不相信以上方案可以優化網頁的性能,那麼我建立了2個Demo頁面。可以測試他們在:資源加載、資源阻塞以及其餘方面的問題。
經過 caniuse 的統計,有84%用戶的瀏覽器支持WOFF字體格式。除此以外,不支持WOFF格式的瀏覽器包括:IE8及其如下、Android上的一些老瀏覽器。所以,這裏提供的優化是針對於支持WOFF字體格式的現代瀏覽器的方案。對於舊瀏覽器依然使用後備字體來展示網頁(好比:Arial = = PS如下:中文的話能夠採用「simsun」,屬於襯線字體),這將給用戶帶來更好的用戶體驗。
這兩種方式會形成如下兩個問題:
(1)額外的請求阻塞
(2)經過它們異步加載字體的時候會出現閃爍問題。
下面咱們將看處處理webfonts更好的方式。
選擇一個webfonts本身使用。不幸的時沒有任何一個licence容許這麼幹。不過值得慶幸的時咱們能夠利用一些開源的字體,好比:Open Sans、Source Sans Pro。當你發現你想要的字體就可以下載它們的「二進制」文件(OTF或者TTF)。
這裏推薦一個網站:Font Squirrel Webfont Generator
(PS:這個網站是用來處理字體的,有捐贈環節的哦~具體功能能夠點進去嘗試一下就知道了)
咱們可以選擇一些額外的方式來移除一些字符。你可以選擇你須要的一些字符出來使用。若是你的網頁全是英文內容,那麼你只須要選擇一些基本字符;若是你得網頁有中文,那麼你可能須要全部的字符。(原文錯誤:Chineese -\> Chinese)
更重要的是最後生成咱們所須要的,包含了字體base64編碼信息的CSS字體文件。
該CSS文件的大小取決於你選擇的字符集合以及相關方面,也許該文件至關的大(最高可達100~300KB)。所以,使用gzip壓縮以及設置強緩存的方式對於用戶來講是很重要的。
不過幸運的是隻有當你網頁的瀏覽者第一次訪問該CSS文件的時候會發出請求。因爲在第一次的時候,用戶本地沒有該字體文件,因此瀏覽器就會去異步加載他們,而且存儲在localStorage中。當用戶的網絡環境較慢的狀況下,可以看到後備字體以及webfonts渲染過程,不過這些只會發生在用戶第一次訪問你網頁的時候。大多數用戶不會太在乎這一細節。
當用戶第二次網頁頁面的時候,瀏覽器將從localStorage中加載CSS文件內容,這種方式至關的快速(5~50ms)。在這種狀況下用戶看不到任何的閃爍,由於全部的操做將是同步進行的,這僅僅只須要幾毫秒的時間。
因爲我使用的是localStorage技術,因此只有客戶端的代碼。
(function(){ function addFont() { var style = document.createElement('style'); style.rel = 'stylesheet'; document.head.appendChild(style); style.textContent = localStorage.sourceSansPro; } try { if (localStorage.sourceSansPro) { // 若是localStorage中有該字體,就直接取出來加載 addFont(); } else { // 首次加載字體咱們須要異步加載它 var request = new XMLHttpRequest(); request.open('GET', '/path/to/source-sans-pro.woff.css', true); request.onload = function() { if (request.status >= 200 && request.status < 400) { // 保存到localStorage中,key=sourceSansPro localStorage.sourceSansPro = request.responseText; addFont(); } } request.send(); } } catch(ex) { // 這裏處理一些同步加載woff功能的瀏覽器 // 避免當localStorage不可用的時候,那麼將每次請求字體帶來的閃爍問題 } }());
優化的流程圖簡圖以下:
(1)解決了除用戶第一次訪問網頁外,其他更屢次訪問時候的請求阻塞問題;
(2)解決了除用戶第一次訪問網頁外,其他訪問的閃爍問題;
(3)減小了第一次請求頁面的渲染時間;
(4)獲得了在Google Page Speed Insights 和 WebPageTest.org 上更高的分數。
英文版本的做者說到本文缺乏一些細節的說明,可以在他博客中留言討論。
英文版本的做者 2014/10/11 更新內容
經過內聯Goole提供的CSS文件的方式,在Google Page Speed Insights中取得了99/100的分數。
英文版本的做者不贊同使用這種方式,由於這種方式會嚴重影響文本的渲染,所以咱們來深刻了解一下其中發生了什麼。
(1)首先咱們定義一個內聯的font faces。
<head> ... <style> @font-face { font-family: 'Source Sans Pro'; font-style: normal; font-weight: 400; src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(http://fonts.gstatic.com/s/sourcesanspro/v9/ODelI1aHBYDBqgeIAH2zlBBHWFfxJXS04xYOz0jw624.woff) format('woff'); } </style> ... </head>
(2)因爲瀏覽器最開始不知道頁面哪個地方會使用到該字體,因此不會去請求這個字體文件。
(3)瀏覽器要等待DOM和CSSOM構建完成。
(4)瀏覽器這時開始從Google Fonts請求字體文件,須要注意的是,這裏會有一個來自於fonts.gstatic.com的額外DNS請求(PS:在國內的環境就不要想google字體的事情了,可使用360的公共CDN服務,很好用,改改URL就行)。
這個timeline說明在DOMContentLoaded事件以前,字體的加載已經開始了。
(5)若是上面的前面還不夠糟糕,大多數瀏覽器將呈現空白文本,在不一樣瀏覽器之間實際的行爲會有所不一樣:
A. 若是請求字體還不可用,IE 會當即使用後備字體呈現,並在字體下載完成以後立刻從新呈現;
B. Firefox 和 Chrome 35+ 會首先下載3秒鐘的字體,若是超過3秒鐘後,會使用後備字體渲染網頁,等到指定字體下載完成後再從新渲染網頁;
C. Safari 和 Chrome 35以前的版本,會等到指定字體下載完成後再渲染網頁(PS:就是不會使用後備字體)。
注:以上說明中沒有表示IE的版本以及Safari的版本號,因此須要本身測試才能算正確。
所以,若是網絡鏈接緩慢,在大多數瀏覽器中將延遲超過3秒的文本渲染。在最壞的狀況下,若是你的字體加載帶有時間限制(因爲一些鏈接很慢的移動設備),Safari 用戶將不會再展現文本,剩下一個空白網頁。若是網頁請求超時,最終將只會呈現一個空白網頁。
更多的信息能夠訪問:Ilya Gregorik's blog
其餘相關資源:
其實英文版本的做者也是翻譯的一篇俄文,這篇俄文來自於:
英文版本原文出自:
http://bdadam.com/blog/loading-webfonts-with-high-performance.html
注:若是你有興趣能夠再看一下英文版本和俄文版本文章下面的評論,裏面還有一些頗有價值的東西,這裏就再也不翻譯了,有時間能夠再整理一下。以上文章若是有翻譯不恰當的地方請在文章後面留言,看見了必定回覆而且修改。
原文出自:http://www.60sky.com