網頁加載速度之中文字體優化篇

Photo of author
Written By CMO

”將“字到底怎麼寫?
”將“字到底怎麼寫?

不久前我們介紹了《Google Analytics跟踪網站頁面速度》,其中我們提到了對網頁字體的優化可以增加網頁加載性能。那麼本篇我們將展開討論如何優化網頁字體來獲得最佳的表現。由於中文字體的文件少則幾兆多則十幾兆,對於Web-font來說可操作性不強,我們將先說說英文字體。文章的後面部分再回到中文字體的解決方案。

TL;DR

為了避免太枯燥的閱讀,如果你不是前端工程師或者是前端技術愛好者,那麼僅僅需要把下面五點建議發給您的小伙伴。

  1. 在服務器開啟HTTP/2,並對靜態資源設置E-TAG和Cache-Control。
  2. 避免使用Google Fonts,將字體文件放在國內可以訪問的CDN或者本地。
  3. 使用<link rel=preload>來提前加載字體文件。
  4. 在@font-face中,使用font-display: swap避免字體阻止期中的空白文本。
  5. 在@font-face中,使用unicode-range獲取所需的中文字體片段。

網頁加載中的字體加載過程

網頁加載過程中的字體渲染
網頁加載過程中的字體渲染

網頁加載的過程大致是一個畫畫的過程。當開始構思時,畫家會構思一個主題(對網頁的HTTP請求),然後會對這個主題(HTML)所需要的元素(DOM 元素)進行填充和佈局(DOM樹)。對每個元素,畫家要決定怎麼畫(獲得CSS,並把CSSOM樹與DOM樹合併),上什麼顏色(假設是CSS中的字體)。所有這些都齊了以後,畫家就可以把畫畫出來了。

那麼這裡又有一個微觀的過程就是上色的時間線(字體顯示時間線):

字體阻止期– 字體交換期– 字體失敗期

  • 阻止期中,畫家在找顏料(字體資源),這段時間畫家不會上色。因此字體並不會顯示。阻止期各個瀏覽器的默認定義不同,一般是3秒。這段時間如果找到顏料,那麼阻止期就會結束,正常上色。如果超時未找到顏料,那麼就會進入字體交換期。
  • 交換期中,畫家依然會在找顏料。不過畫家會開始用備用顏料上色了。比如找不到藍色,那麼就用寶藍代替。在這段時間裡如果畫家找到了顏色,那麼會放棄寶藍,用藍色再上一次,所謂的“交換”。
  • 失敗期中,畫家會接受找不到顏料的事實。用備用顏料上色。

我們從上面的字體顯示時間線可以看出,要避免的是過長的阻止期,因為這段時間文字不會顯示!另外對於一些公司的Logo用特定字體顯示的情況,我們希望能夠早點畫出正確字體的文字,因此需要優化字體載入的時間。我們下面先講優化字體載入時間。

利用<link rel=preload>提前加載字體文件

我們從畫畫的過程中可以看到,畫家決定使用那種顏色是後面考慮的問題。但是如果我們預先在主題構思的時候想到這一點就可以提前去加載這個字體文件。

將字體預先載入效果解說
將字體預先載入效果解說

這樣我們就可以把<link rel=preload>放到HTML的<head></head>中,讓瀏覽器提前下載字體文件,而不用等DOM樹完成後等CSS下載後才去請求。由於下載字體使用了額外的HTTP請求,因此HTTP/2可以大幅提高性能,它不需要受六個並發HTTP請求的限制。

具體的寫法如下:

< link rel =” preloadhref =” your-font.woff2as =” fonttype =” font/woff2crossorigin >

當你在服務器上設置好E-TAG(告訴客戶端你的資源有沒有變化)和Cache-control(告訴客戶端緩存時間長度)後,這些字體資源就不需要多次下載,以節省時間。

當然,不要忘了,部署preload的同時,你還可以把對字體的引用放入HTML中的inline CSS中。這樣不用等CSS文件下完瀏覽器就知道需要請求這個資源了。

使用font-display: swap;控製字體阻止期

在CSS的@font-face規則中,你可以添加font-display: swap;語句來對字體的阻止期進行控制。默認是auto,與block近似。而改為swap後,意味著阻止期為0,而交換期為無限長

這樣一來你便可以避免網頁出現空白文本,而立即用替換字體顯示內容,一旦需要的字體下載完成後就可以替換原來的字體正確顯示。

中文字體的優化

中文字體通常不建議讓用戶特別去下載字體文件,而是使用用戶本地已有的字體文件,如宋體、黑體等。

另外,上面提到了所謂的替換字體,你可以在font-family中設置。比如

font-family: ‘microsoft yahei’, sans-serif;

瀏覽器會根據這個先後順序來選擇匹配字體。在上面的例子中,如果雅黑不可用,那麼會用萬能字體sans-serif來代替。如果你希望英文字符使用別的字符那麼可以在雅黑前面加上。

雖然不特別添加中文字體可以正常顯示中文,但是你還是需要添加中文字體的。比如下面這個例子,這兩個字的Unicode都是U+5C06。如果你不指定中文字體就會出現爪字頭的,而不是夕字頭的將。同樣的還有其他字比如“寫”,下面的“與”的一橫會出頭。

默認日語的“將”字寫法
默認日語的“將”字寫法

如果你必須使用“正常人”電腦裡不會安裝的字體,那麼你可以考慮使用unicode-range,這樣做的好處是你不需要下載幾個M的字體文件,而只需要把用到的加載進來。比如下面是基本漢字集的片段:

unicode-range:U+4E00-9FA5;

國內也有Web Font供應商提供這些雲服務,也需要把文字預先提交生成特定的字體片段文件。

總結+參考資料

本篇我們介紹了一些基本的優化網頁字體性能的手段,希望對你有所幫助。一些在開發中的Font-API我們沒有涉及。我們參考了下面幾篇文章,你可以擴展閱讀。

《網頁字體優化– Ilya Grigorik》

《Web Performance Made Easy: Google I/O 2018 edition》

《CSS unicode-range特定字符使用font-face自定義字體– 張鑫旭》

最後這裡有Web Font Recipes repo,Zach Leatherman做的一些Demo。你可以在Chrome開發工具中用低網速來進行演示。