Web 字体优化

在 Web 性能优化领域,我们通常会关注加载速度、渲染性能和网络请求等核心问题。然而,Web 字体优化却是一个容易被忽视但影响显著的优化点。本文将系统介绍为什么需要关注字体优化、如何高效实现优化,以及一些实用技巧,帮助你打造既美观又高效的网站。


为什么要做 Web 字体优化?

在开始之前,我们需要明确一个问题:字体优化真的重要吗?答案是肯定的。当页面加载自定义字体时,字体文件往往会成为性能瓶颈。如果你曾经遇到过这样的情况:页面加载时,文字先以系统默认字体显示,待字体文件加载完成后,页面突然切换到目标字体——这就是闪烁的未加载文本(FOIT, Flash of Invisible Text)现象,它会严重影响用户体验。

字体包的大小

现代字体文件的体积往往相当可观。特别是支持多语言的字体包,可能包含数千甚至上万个字形和符号。但在实际使用中,我们往往只需要其中的一小部分字符集。比如使用 RobotoOpen Sans 等流行字体时,如果页面仅包含英文内容,加载完整的字体包就显得浪费资源。

这时,字体子集化(Font Subsetting)就成为关键优化手段。通过只加载必需的字符集,可以大幅减小文件体积。

参考:可以使用 Google Fonts 等工具精确选择所需字符集,有效减少文件体积。

@font-face {
  font-family: "CustomFont";
  src: url("/fonts/custom-font.woff2") format("woff2");
  font-display: swap;
}

上述代码使用 woff2 格式的字体文件,并通过 font-display: swap 确保在字体加载完成前先使用系统字体显示内容。

字体包缓存

字体文件不仅体积大,加载速度也相对较慢。合理的缓存策略可以让浏览器在用户第二次访问时直接从缓存读取字体文件,无需重新下载。

可以通过 HTTP 响应头中的 Cache-ControlExpires 设置缓存策略。例如:

Cache-Control: public, max-age=31536000, immutable

这里 max-age=31536000 表示缓存有效期为一年,immutable 表示该资源不会发生变化,浏览器可以安全地长期缓存。

参考:Cache-Control 用于指示浏览器如何缓存资源,max-age 定义了资源的缓存时长。


怎么优化 Web 字体加载?

使用原生字体

使用原生系统字体优化

This text uses the native system font, which is already optimized for font loading speed.


这里使用的是原生系统字体,已经优化了字体加载速度。

实际上,完全可以避免使用外部字体文件。使用系统字体或常见的无衬线字体,不仅加载速度快,还能避免外部字体带来的性能开销。

ArialVerdanaHelvetica 等系统字体为例,浏览器可以直接调用操作系统预装的字体,加载速度极快。无论用户使用 macOS、Windows 还是 Linux,这些字体的显示效果都基本一致。

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
    "Oxygen", sans-serif;
}

这些字体已预装在用户的操作系统中,避免了字体文件的网络加载,是一种简单高效的优化方案。

使用字体预加载

使用字体预加载优化

This text uses a custom font that is preloaded with the <link rel="preload"> tag, which optimizes the font loading speed.


上面使用的了预加载字体文件,从而优化了字体加载速度。

字体预加载可以让浏览器提前加载关键字体,而不是等到需要时才开始下载。这样可以减少字体加载延迟,让页面渲染更加流畅。

<link
  rel="preload"
  href="/fonts/custom-font.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
/>

这段代码告诉浏览器在页面渲染前优先加载 custom-font.woff2 字体文件,确保字体在需要时已经准备就绪。

参考:preload 可以提前加载关键资源,减少页面加载时的延迟,显著提高页面响应速度。

使用 font-display

如果不希望文本在字体加载完成前出现空白或闪烁,font-display 属性可以控制浏览器在字体加载过程中如何显示文本。

  • font-display: swap:在字体加载前使用系统字体渲染文本,加载完成后立即切换到目标字体。这是最常用的方案,可以有效解决文本闪烁问题。
  • font-display: fallback:如果字体加载时间过长,使用备用字体,直到自定义字体加载完成。
@font-face {
  font-family: "CustomFont";
  src: url("/fonts/custom-font.woff2") format("woff2");
  font-display: swap;
}

swap 是推荐选项,它确保用户在字体加载时能看到文本内容,而不是空白区域。

异步加载字体

更进一步,可以使用 JavaScript 异步加载字体文件。这样不仅可以避免阻塞页面渲染,还能精确控制字体的加载时机,实现更优的性能表现。例如使用 Font Face Observer 库监听字体加载状态:

import FontFaceObserver from "fontfaceobserver";

const font = new FontFaceObserver("CustomFont");
font.load().then(function () {
  document.documentElement.classList.add("custom-font-loaded");
});

这种方法的优势在于:字体加载完成后再应用到页面,不会影响其他内容的渲染。页面内容可以提前展示,无需等待字体文件下载完成。


小测

如果想要美观的字体,Web 字体优化往往最有效的是什么?
1.使用原生字体
2.字体预加载
3.减少字体包大小

参考文档

  • 优化网页字体 :来自Web Dev,详细介绍了如何优化网页字体,包括字体预加载、字体子集化、字体缓存等策略。