包含您可能不需要的所有樣式變化版本的「full」WebFont,以及可能會未使用的所有字符,都可能輕鬆導致下載超過 MB。這篇文章將說明如何改善 WebFonts 的載入,讓訪客只下載要使用的內容。
為解決大型檔案包含所有變化版本的問題,@font-face
CSS 規則是專為可將字型系列分割為資源集合。例如萬國碼 (Unicode) 子集和不同的樣式變化版本。
根據這些宣告,瀏覽器會判斷所需的子集和變化版本,並下載轉譯文字所需的最少集合,使用起來相當方便。然而,如果不留意,這也可能會在關鍵轉譯路徑中造成效能瓶頸,並延遲文字轉譯。
預設行為
延遲載入字型具有重大隱藏影響,可能會導致文字延遲顯示。瀏覽器必須建構轉譯樹狀結構,此樹狀結構取決於 DOM 和 CSSOM 樹狀結構,才能知道轉譯文字需要哪些字型資源。因此,在其他重要資源之後,字型要求會一直延遲,且瀏覽器在擷取資源之前可能會無法轉譯文字。
- 瀏覽器要求 HTML 文件。
- 瀏覽器會開始剖析 HTML 回應並建構 DOM。
- 瀏覽器會探索 CSS、JS 和其他資源,並調派要求。
- 瀏覽器收到所有 CSS 內容後,便會建構 CSSOM,並與 DOM 樹狀結構結合,以建構算繪樹狀結構。
- 字型要求會在轉譯樹狀結構後發送,指出需要哪種字型變化版本才能轉譯網頁指定文字。
- 瀏覽器會執行版面配置,並將內容繪製到螢幕上。
- 如果字型無法使用,瀏覽器可能無法顯示任何文字像素。
- 字型可用後,瀏覽器會繪製文字像素。
網頁內容首次繪製之間的「賽程」(可在建構轉譯樹狀結構後不久執行),而字型資源的要求則是「空白文字問題」,亦即瀏覽器可能會轉譯網頁版面配置,卻省略任何文字。
藉由預先載入 WebFonts 並使用 font-display
控制瀏覽器在無法使用字型上的行為後,就能避免空白頁面和版面配置因為字型載入而變動。
預先載入 WebFont 資源
如果您的網頁很有可能需要使用預先已知的網址代管的特定 WebFont,則可採用資源優先順序。使用 <link rel="preload">
會在關鍵轉譯路徑中提早觸發 WebFont 要求,不必等待系統建立 CSSOM。
自訂文字顯示延遲
預先載入功能更有機會在網頁轉譯時取得 WebFont,但不保證一定能使用 WebFont。使用 font-family
目前不支援的文字轉譯文字時,您還是需要考量瀏覽器的行為。
在「避免在字型載入期間隱藏文字」文章中,您可以看到預設瀏覽器的行為不一致。
不過,您可以使用 font-display
讓新式瀏覽器瞭解您希望瀏覽器的行為。
與某些瀏覽器實作的現有字型逾時行為類似,font-display
會將字型下載的生命週期劃分為三個主要時段:
- 第一個句號是字型區塊期間。在這段期間,如果未載入字型,任何嘗試使用該字型的元素都必須改為顯示隱藏式備用字型。如果字型在區塊期間成功載入,系統隨後會正常使用字型。
- 字型交換週期緊接在字型區塊週期結束後就會立即發生。在這段期間,如果未載入字型,任何嘗試使用該字型的元素都必須改為顯示備用字型。如果字型在交換期間成功載入,系統就會正常使用字型。
- 字型失敗期限會立即出現在字型替換期過後。如果在這段期間內尚未載入字型,系統會將其標示為失敗的載入,導致一般字型遞補。否則,系統會正常使用字型。
瞭解這些週期,您就可以使用 font-display
根據下載或下載時間決定字型的顯示方式。
如要使用 font-display
屬性,請將其新增至 @font-face
規則:
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
font-display: auto; /* or block, swap, fallback, optional */
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
url('/fonts/awesome-l.woff') format('woff'),
url('/fonts/awesome-l.ttf') format('truetype'),
url('/fonts/awesome-l.eot') format('embedded-opentype');
unicode-range: U+000-5FF; /* Latin glyphs */
}
font-display
目前支援下列值範圍:
auto
block
swap
fallback
optional
如要進一步瞭解如何預先載入字型,以及 font-display
屬性,請參閱下列文章:
字型載入 API
如果搭配使用 <link rel="preload">
和 CSS font-display
,您可充分控製字型的載入和轉譯方式,而且不會增加太多負擔。不過,如果您需要額外的自訂項目,且願意讓執行 JavaScript 造成負擔,則可選擇其他方法。
字型載入 API 提供指令碼介面,可讓您定義及操控 CSS 字型、追蹤下載進度,以及覆寫預設的延遲載入行為。舉例來說,如果您確定需要特定字型變化版本,可以定義該字型,並指示瀏覽器立即擷取字型資源:
var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});
// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
// apply the font (which may re-render text and cause a page reflow)
// after the font has finished downloading
document.fonts.add(font);
document.body.style.fontFamily = "Awesome Font, serif";
// OR... by default the content is hidden,
// and it's rendered after the font is available
var content = document.getElementById("content");
content.style.visibility = "visible";
// OR... apply your own render strategy here...
});
此外,由於您可以檢查字型狀態 (透過 check()
) 方法並追蹤下載進度,因此也可以定義在網頁上顯示文字的自訂策略:
- 您可以保留所有文字轉譯,直到字型顯示為止。
- 您可以為每個字型設定自訂逾時。
- 您可以使用備用字型來解除封鎖轉譯,並在取得字型後,插入使用所需字型的新樣式。
最棒的是,您也可以針對網頁上的不同內容,混搭上述策略。 舉例來說,您可以延遲部分區段的文字轉譯時間,直到字型可用為止、使用備用字型,然後在字型下載完畢後重新轉譯。
必須適當地快取快取
字型資源通常是不會經常更新的靜態資源。因此,這些參數非常適合用於長時間效期上限,請務必為所有字型資源指定條件式 ETag 標頭和最佳 Cache-Control 政策。
如果您的網頁應用程式使用服務工作站,則使用快取優先策略提供字型資源適用於大多數用途。
請勿使用 localStorage
或 IndexedDB 儲存字型,每種字型各有一組效能問題。瀏覽器的 HTTP 快取提供最佳、最強大的機制來將字型資源提供給瀏覽器。
WebFont 載入檢查清單
- 使用
<link rel="preload">
、font-display
或 Font Loading API 自訂字型載入和轉譯:預設的延遲載入行為可能會導致文字轉譯延遲。這些網路平台功能可讓您針對特定字型覆寫這個行為,並為網頁上的不同內容指定自訂轉譯和逾時策略。 - 指定重新驗證和最佳快取政策:字型是不常更新的靜態資源。確認您的伺服器提供長期 max-age 時間戳記和重新驗證權杖,以允許在不同頁面之間有效重複使用字型。如果您使用服務工作站,就適合採用快取優先策略。
使用 Lighthouse 自動測試 WebFont 載入行為
Lighthouse 可協助您自動執行相關程序,確保您遵循網站字型的最佳做法。
以下稽核有助於確保網頁持續遵循網站字型最佳化的最佳做法: