优化 Google 字体性能
已发表: 2022-03-10公平地说,谷歌字体很受欢迎。 截至撰写本文时,它们在网络上的浏览量已超过 29 万亿次,原因很容易理解——该集合让您可以访问 900 多种精美字体,您可以在您的网站上免费使用。 如果没有 Google 字体,您将仅限于安装在用户设备上的少数“系统字体”。
系统字体或“Web 安全字体”是跨操作系统最常预装的字体。 例如,Arial 和 Georgia 与 Windows、macOS 和 Linux 发行版打包在一起。
像所有好东西一样,谷歌字体确实是有代价的。 每种字体都有一个权重,Web 浏览器需要先下载它们才能显示。 使用正确的设置,额外的加载时间并不明显。 但是,如果弄错了,您的用户可能要等待几秒钟才能显示任何文本。
谷歌字体已经优化
Google Fonts API 不仅仅是向浏览器提供字体文件,它还执行智能检查以查看它如何以最优化的格式提供文件。
让我们看看 Roboto,GitHub 告诉我们常规变体重 168kb。

但是,如果我从 API 请求相同的字体变体,我会得到这个文件。 只有11kb。 这个怎么可能?
当浏览器向 API 发出请求时,Google 首先会检查浏览器支持的文件类型。 我使用的是最新版本的 Chrome,它与大多数浏览器一样支持 WOFF2,因此字体以高度压缩的格式提供给我。
如果我将用户代理更改为 Internet Explorer 11,则会改为使用 WOFF 格式的字体。
最后,如果我将用户代理更改为 IE8,那么我将获得 EOT(嵌入式 OpenType)格式的字体。
Google Fonts 为每种字体维护 30 多种优化变体,并自动检测并为每个平台和浏览器提供最佳变体。
— Ilya Grigorik,网络字体优化
这是谷歌字体的一个很棒的功能,通过检查用户代理,他们能够为支持这些格式的浏览器提供性能最高的格式,同时仍然在旧浏览器上一致地显示字体。
浏览器缓存
谷歌字体的另一个内置优化是浏览器缓存。
由于谷歌字体无处不在,浏览器并不总是需要下载完整的字体文件。 例如,SmashingMagazine 使用一种名为“Mija”的字体,如果这是您的浏览器第一次看到该字体,则需要在显示文本之前将其完全下载,但下次您使用该字体访问网站时,浏览器将使用缓存的版本。
随着 Google Fonts API 的使用越来越广泛,您网站或页面的访问者很可能已经在他们的浏览器缓存中拥有您的设计中使用的任何 Google 字体。
— 常见问题解答,谷歌字体
谷歌字体浏览器缓存设置为一年后过期,除非缓存被尽快清除。
注意: Mija 不是 Google 字体,但缓存的原则不是特定于供应商的。
进一步优化是可能的
尽管 Google 在优化字体文件的交付方面投入了大量精力,但您仍然可以在实施中进行优化,以减少对页面加载时间的影响。
1.限制字体系列
最简单的优化是简单地使用更少的字体系列。 每种字体最多可以增加 400kb 到您的页面重量,再乘以几个不同的字体系列,突然间您的字体重量就超过了整个页面。
我建议使用不超过两种字体,一种用于标题,另一种用于内容通常就足够了。 通过正确使用字体大小、粗细和颜色,您甚至可以使用一种字体来获得出色的外观。

2.排除变体
由于 Google 字体的高质量标准,许多字体系列都包含所有可用的字体粗细:
- 薄 (100)
- 细斜体 (100i)
- 光 (300)
- 浅斜体 (300i)
- 常规 (400)
- 常规斜体 (400i)
- 中型 (600)
- 中等斜体 (600i)
- 粗体 (700)
- 粗斜体 (700i)
- 黑色 (800)
- 黑色斜体 (800i)
这对于可能需要所有 12 个变体的高级用例非常有用,但对于常规网站,这意味着当您可能只需要 3 或 4 个时下载所有 12 个变体。
例如,Roboto 字体系列重约 144kb。 但是,如果您只使用 Regular、Regular Italic 和 Bold 变体,则该数字将降至 ~36kb。 节省 75%!
实现 Google 字体的默认代码如下所示:
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
如果这样做,它将仅加载“常规 400”变体。 这意味着所有浅色、粗体和斜体文本都不会正确显示。
要加载所有字体变体,我们需要在 URL 中指定权重,如下所示:
<link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i" rel="stylesheet">
很少有网站会使用从 Thin (100) 到 Black (900) 的所有字体变体,最佳策略是仅指定您计划使用的权重:
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,600" rel="stylesheet">
这在使用多个字体系列时尤其重要。 例如,如果您使用 Lato 作为标题,则只请求粗体变体(可能还有粗斜体)是有意义的:
<link href="https://fonts.googleapis.com/css?family=Lato:700,700i" rel="stylesheet">
3. 合并请求
我们在上面使用的代码片段调用了 Google 的服务器 ( fonts.googleapis.com
),这称为 HTTP 请求。 一般来说,您的网页需要发出的 HTTP 请求越多,加载所需的时间就越长。

如果你想加载两种字体,你可以这样做:
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
这会起作用,但会导致浏览器发出两个请求。 我们可以通过将它们组合成一个请求来优化它,如下所示:
<link href="https://fonts.googleapis.com/css?family=Roboto|Open+Sans:400,400i,600" rel="stylesheet">
单个请求可以容纳多少字体和变体没有限制。
4. 资源提示
资源提示是现代浏览器支持的一项功能,可以提高网站性能。 我们将看一下两种类型的资源提示:“DNS Prefetching”和“Preconnect”。
注意:如果浏览器不支持现代功能,它会简单地忽略它。 所以你的网页仍然会正常加载。
DNS 预取
DNS 预取允许浏览器在页面开始加载后立即开始连接到 Google 的字体 API ( fonts.googleapis.com
)。 这意味着当浏览器准备好发出请求时,一些工作已经完成。
要为 Google 字体实现 DNS 预取,您只需将这一行添加到您的网页<head>
中:
<link rel="dns-prefetch" href="//fonts.googleapis.com">
预连接
如果您查看 Google 字体嵌入代码,它似乎是一个 HTTP 请求:
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet">
但是,如果我们访问该 URL,我们可以看到另外三个对不同 URL https://fonts.gstatic.com 的请求。 每个字体变体的一个额外请求。

这些额外请求的问题在于,在对https://fonts.googleapis.com/css
的第一个请求完成之前,浏览器不会开始处理这些请求。 这就是 Preconnect 的用武之地。
预连接可以被描述为预取的增强版本。 它是在浏览器要加载的特定 URL 上设置的。 它不仅执行 DNS 查找,还完成了 TLS 协商和 TCP 握手。
就像 DNS Prefetching 一样,只需一行代码即可实现:
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
只需添加这行代码就可以将您的页面加载时间减少 100 毫秒。 这可以通过在初始请求旁边启动连接来实现,而不是等待它首先完成。
5.本地托管字体
Google 字体是根据“自由”或“自由软件”许可获得许可的,这使您可以自由使用、更改和分发字体而无需请求许可。 这意味着如果您不想使用 Google 的托管,您可以自行托管字体!
所有字体文件都可以在 Github 上找到。 还提供包含所有字体的 zip 文件 (387MB)。
最后,还有一个帮助服务,可以让您选择要使用的字体,然后它会提供执行此操作所需的文件和 CSS。
在本地托管字体有一个缺点。 当您下载字体时,您将它们保存为当时的状态。 如果它们得到改进或更新,您将不会收到这些更改。 相比之下,当从 Google Fonts API 请求字体时,始终会为您提供最新版本。

请注意 API 中的lastModified
参数。 字体会定期修改和改进。
6.字体显示
我们知道浏览器下载 Google 字体需要时间,但是在文本准备好之前会发生什么? 很长一段时间,浏览器会在文本应该出现的地方显示空白,也称为“FOIT”(不可见文本的Flash)。
推荐阅读: Chris Coyier 的“FOUT, FOIT, FOFT”
什么都不显示对最终用户来说可能是一种不和谐的体验,更好的体验是最初将系统字体显示为备用字体,然后在字体准备好后“交换”字体。 这可以使用 CSS font-display
属性来实现。
通过添加font-display: swap;
对于@font-face 声明,我们告诉浏览器显示备用字体,直到 Google 字体可用。
@font-face { font-family: 'Roboto'; src: local('Roboto Thin Italic'), url(https://fonts.gstatic.com/s/roboto/v19/KFOiCnqEu92Fr1Mu51QrEz0dL-vwnYh2eg.woff2) format('woff2'); font-display: swap; }
2019 年,谷歌宣布他们将增加对 font-display:swap 的支持。 您可以通过在字体 URL 中添加一个额外的参数来立即开始实现这一点:
https://fonts.googleapis.com/css?family=Roboto&display=swap
7.使用Text
参数
Google Fonts API 的一个鲜为人知的特性是text
参数。 这个很少使用的参数允许你只加载你需要的字符。
例如,如果您有一个 text-logo 需要是唯一字体,您可以使用text
参数仅加载 logo 中使用的字符。
它是这样工作的:
https://fonts.googleapis.com/css?family=Roboto&text=CompanyName
显然,这种技术非常具体,只有少数实际应用。 但是,如果您可以使用它,它最多可以将字体重量减少 90%。
注意:使用text
参数时,默认只加载“普通”字体粗细。 要使用另一个权重,您必须在 URL 中明确指定它。
https://fonts.googleapis.com/css?family=Roboto:700&text=CompanyName
包起来
据估计,前 100 万个网站中有 53% 使用 Google 字体,实施这些优化可以产生巨大的影响。
您尝试过以上几种? 在评论部分让我知道。