最佳化網路字型

在前幾個單元中,您已瞭解如何最佳化 HTML、CSS、JavaScript 和媒體資源。本單元將介紹幾種最佳化網頁字體的方法。

網頁字型可能會影響網頁在載入時間和算繪時間的效能。大型字型檔案可能需要一段時間才能下載,並對首次顯示內容所需時間 (FCP) 造成負面影響,而錯誤的 font-display可能會導致不必要的視覺算繪變化。

在討論如何最佳化網頁字型之前,瞭解瀏覽器如何探索網頁字型很有幫助,這樣您就能瞭解 CSS 如何在特定情況下防止擷取不必要的網頁字型。

探索

網頁的網路字型是在 CSS 樣式表中使用 @font-face 宣告定義:

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

上述程式碼片段定義名為 "Open Sans"font-family,並告知瀏覽器要在何處尋找相應的網頁字型資源。"Open Sans"為節省頻寬,瀏覽器會先判斷目前網頁的版面配置是否需要網路字型,再下載該字型。

h1 {
  font-family: "Open Sans";
}

在上述 CSS 程式碼片段中,瀏覽器會在剖析網頁 HTML 中的 <h1> 元素時,下載 "Open Sans" 字型檔案。

preload

如果 @font-face 宣告是在外部 CSS 樣式表定義,瀏覽器必須先下載 CSS 樣式表,才能開始下載這些宣告。因此網頁字型屬於延遲探索的資源,但您可以採取一些做法,協助瀏覽器更快探索網頁字型。

您可以使用 preload 指令,提早要求網頁字型資源。preload 指令可讓網頁字型在載入網頁期間提早被發現,瀏覽器會立即開始下載這些字型,不必等待 CSS 樣式表下載及剖析完畢。preload 指令不會等到網頁需要字型時才載入。

<!-- The `crossorigin` attribute is required for fonts-even
     self-hosted ones, as fonts are considered CORS resources. -->
<link rel="preload" as="font" href="/fonts/OpenSans-Regular-webfont.woff2" crossorigin>

內嵌@font-face聲明

您可以使用 <style> 元素,在 HTML 的 <head> 中內嵌轉譯阻斷 CSS (包括 @font-face 宣告),在載入網頁期間更早探索字型。在這種情況下,瀏覽器會在載入網頁時更早發現網頁字型,因為不需要等待下載外部 CSS 樣式表。

內嵌 @font-face 宣告比使用 preload 提示更具優勢,因為瀏覽器只會下載顯示目前網頁所需的字型。這樣就能避免下載未使用的字型。

下載

瀏覽器發現網頁字型並確認目前頁面版面配置需要這些字型後,即可下載。網頁字型的數量、編碼和檔案大小,都會顯著影響瀏覽器下載及算繪網頁字型的速度。

自行託管網頁字型

網頁字型可透過第三方服務 (例如 Google Fonts) 提供,也可以在來源上自行代管。使用第三方服務時,網頁必須先開啟與供應商網域的連線,才能開始下載所需的網頁字型。這可能會延遲網頁字型的探索和後續下載作業。

使用 preconnect 資源提示可減少這項額外負荷。使用 preconnect,您可以指示瀏覽器比平常更早開啟跨來源的連線:

<link rel="preconnect" href="https://fonts.googleapis.com">  
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

上述 HTML 片段會提示瀏覽器與 fonts.googleapis.com 建立連線,並與 fonts.gstatic.com 建立 CORS 連線。部分字型提供者 (例如 Google Fonts) 會從不同來源提供 CSS 和字型資源。

您可以自行代管網頁字型,免除第三方連結的需求。在大多數情況下,自行代管網頁字型會比從跨來源下載字型更快。如果您打算自行代管網頁字型,請確認網站使用內容傳遞聯播網 (CDN)HTTP/2 或 HTTP/3,並為網站所需的網頁字型設定正確的快取標頭。

使用 WOFF2,且只能使用 WOFF2

WOFF2 獲得廣泛的瀏覽器支援,且壓縮效果最佳,比 WOFF 壓縮率高出 30%。檔案縮小後,下載速度會更快。WOFF2 格式通常是唯一需要的格式,可確保與新式瀏覽器完全相容。

建立網頁字型子集

網頁字型通常包含各種不同的字形,可呈現不同語言使用的各種字元。如果網頁只提供一種語言的內容,或使用單一字母,您可以透過子集化減少網頁字型的大小。通常是指定數字或一系列的Unicode 碼位

子集是原始網頁字型檔案中包含的字形縮減集。舉例來說,網頁可能會提供拉丁字元的特定子集,而不是提供所有字形。視需要的子集而定,移除字形可大幅縮減字型檔案大小。

部分網頁字型供應商 (例如 Google Fonts) 會透過查詢字串參數自動提供子集。舉例來說,https://fonts.googleapis.com/css?family=Roboto&subset=latin 網址會提供含有 Roboto 網頁字型的 CSS 樣式表,但只使用拉丁字母。

如果您決定自行代管網頁字型,下一步就是使用 glyphangersubfont 等工具,自行產生並代管這些子集。

不過,如果您沒有自行代管網路字型的能力,可以指定額外的text查詢字串參數,只包含網站所需的 Unicode 碼位,藉此建立 Google Fonts 提供的網路字型子集。舉例來說,如果網站上的顯示網頁字型只需要「歡迎」一詞的少量字元,您可以透過下列網址,向 Google Fonts 要求該子集:https://fonts.googleapis.com/css?family=Monoton&text=Welcome。如果網站上需要使用這種極端子集,就能大幅減少網站上單一字體所需的網頁字型資料量。

字型顯示

瀏覽器探索並下載網頁字型後,即可進行算繪。根據預設,瀏覽器會封鎖使用網頁字型的文字轉譯作業,直到字型下載完成為止。你可以調整瀏覽器的文字算繪行為,並使用 font-display CSS 屬性設定在網頁字型完全載入前顯示或不顯示的文字。

block

font-display 的預設值為 block。使用 block 時,瀏覽器會封鎖任何使用指定網路字型的文字轉譯作業。不同瀏覽器的行為稍有不同。Chromium 和 Firefox 會先封鎖最多 3 秒的算繪作業,然後再使用備援字型。Safari 會無限期封鎖,直到網頁字型載入為止。

swap

swap 是最廣泛使用的 font-displayswap 不會封鎖算繪作業,並會在換入指定的網頁字型前,立即在備用字型中顯示文字。這樣一來,您就能立即顯示內容,不必等待網頁字型下載完畢。

不過,如果備用網頁字型和 CSS 中指定的網頁字型在行高、字距和其他字型指標方面差異很大,swap 就會導致內容明顯位移。

這通常不會導致 Cumulative Layout Shift (CLS) 變差,因為 block 需要假設使用備用字型來配置網頁,即使文字本身未顯示,兩者都會受到內容位移的影響,但視覺效果可能會更不協調。block

fallback

font-displayfallback 值是 blockswap 之間的折衷方案。與 swap 不同,瀏覽器會封鎖字型的算繪作業,但只會在極短的時間內換入備用文字。不過,與 block 不同的是,封鎖期極短。

在快速網路中,如果網頁字型下載速度很快,網頁的初始算繪會立即使用網頁字型,因此使用 fallback 值效果良好。不過,如果網路速度緩慢,系統會在封鎖期結束後先顯示備用文字,然後在網頁字型載入後替換。

optional

optional 是最嚴格的 font-display 值,只有在網頁字型資源於 100 毫秒內下載完畢時,才會使用該資源。如果網頁字型載入時間超過這個值,網頁就不會使用該字型,瀏覽器會使用目前導覽的備用字體,同時在背景下載網頁字型並放入瀏覽器快取。

因此,後續的網頁瀏覽作業可以立即使用網頁字型,因為系統已下載該字型。font-display: optional 可避免 swap 造成的視覺變化,但如果網頁字型在初始網頁瀏覽中載入時間過晚,部分使用者就看不到。

字型範例

學以致用

瀏覽器何時會下載網頁字型資源 (假設不是使用 preload 指令擷取)?

只要在 CSS 樣式表發現對該字型的參照。
請再試一次。
網頁的 CSSOM 建構完成,且系統判斷目前版面配置需要網頁字型時。
答對了!

向所有新式瀏覽器放送網頁字型時,唯一 (也是最有效率) 的必要格式為何?

WOFF2
答對了!
WOFF
請再試一次。
TTF
請再試一次。
EOT
請再試一次。

即將播放:程式碼分割 JavaScript

瞭解字型最佳化後,您現在可以前往下一個模組,瞭解如何透過程式碼分割延遲載入 JavaScript,這項主題有助於大幅提升使用者網頁的初始載入速度。這樣做可盡量減少網頁啟動階段的頻寬和 CPU 爭用情形,因為使用者很可能在這段時間與網頁互動。