Web 字体优化

大家可能会想,Web 性能优化总是跟加载、渲染、网络请求这些大话题挂钩。但当你细心一想,Web 字体优化,真的是被很多人忽略的一个点。今天,我们来讲讲为什么你需要关心 Web 字体优化,怎么做才最有效,还有一些小窍门,让你的网站既好看又高效。


为什么要做 Web 字体优化?

好了,开始之前你可能在想,字体优化真的有那么重要吗?哎呦,告诉你,这事儿可不小。你试想一下,当你的页面加载时,尤其是带有自定义字体的页面,字体文件就成了“性能杀手”。你是不是有过这样的经历:页面加载一会儿,文字显示成了奇怪的默认字体,等到字体文件加载完成后,页面才突然“刷”成正常的字体?这就是我们常说的闪烁的未加载文本(FOIT,Flash of Invisible Text),它让用户体验直接掉价。

字体包的大小

你知道吗,现代字体文件能有多大?非常大。尤其是那些支持多语言的字体文件,可能会大得离谱。你要知道,很多字体库包含了成千上万的字形和符号,但如果你只是用到其中的几种字符集,加载整个字体文件简直是浪费。

更进一步讲,如果你使用的是例如 RobotoOpen Sans 这类字体包,字体文件的大小可以很大,但你可能只需要其中很小一部分——只包含英文字符,或者只有常见的几种符号。这时,字体子集化(Font Subsetting)就显得尤为重要了。

MDN:你可以使用像 Google Fonts 这样的工具来精确选择你需要的字符集,减少文件体积。

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

上面的代码告诉浏览器,使用 woff2 格式的字体文件,并且在字体加载完成之前,先用系统字体显示内容。

字体包缓存

字体文件不仅大,而且加载慢。别看浏览器缓存其他资源,字体文件也能缓存起来!只要你合理设置缓存策略,用户第二次访问你的页面时,就不需要重新加载字体文件,直接从缓存里取,省时又省力。

你可以在 HTTP 请求头中添加 Cache-ControlExpires,来告诉浏览器,字体文件能缓存多久。比如:

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

什么意思?max-age=31536000 表示缓存有效期为一年,immutable 则意味着这个字体文件不会变,所以浏览器可以放心地长期缓存。

MDNCache-Control 是告诉浏览器如何缓存资源的一种方法,而 max-age 就是告诉浏览器多久后才需要重新请求资源。


怎么优化 Web 字体加载?

使用原生字体

使用原生系统字体优化

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


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

你知道你完全可以避免使用外部字体文件吗?对,你没听错,使用系统字体或者常见的无衬线字体,不光省时,还能避免加载外部字体文件带来的性能开销。

就拿 ArialVerdanaHelvetica 这类系统字体来说,浏览器加载时直接取系统字体,速度飞快。而且,用户用的是 Mac、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 字体文件先加载好”,这样字体加载完成时,页面内容能迅速渲染出来。

MDNpreload 可以提前加载你可能需要的资源,减少页面加载时的延迟。合适的预加载能大幅提高页面响应速度。

使用 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,详细介绍了如何优化网页字体,包括字体预加载、字体子集化、字体缓存等策略。