Privacy & Security

如何在本地托管字体,而不是使用 Google Fonts

一份兼顾隐私的实用指南,介绍如何从自己的域名下载、子集化、提供并测试 Web 字体。

The Wux Webtools Team The Wux Webtools Team 9 分钟阅读 人工智能辅助,人工审核
Illustration of locally hosted web font files being served from a website instead of a third-party service.
目录
  1. 为什么要自行托管 Google Fonts?
  2. 自行托管后会发生什么变化
  3. 第 1 步:审计你实际使用的内容
  4. 第 2 步:下载正确的字体文件
  5. 第 3 步:在适当情况下对子集化字体
  6. 第 4 步:编写你的 `@font-face` 规则
  7. 第 5 步:移除外部 Google Fonts 调用
  8. 第 6 步:设置缓存头
  9. 第 7 步:只考虑预加载关键字体
  10. 第 8 步:测试隐私和性能
  11. 应避免的常见错误
  12. 托管过多字重
  13. 忘记斜体
  14. 保留旧的 Google CSS 链接
  15. 提供字体但没有长期缓存
  16. 忽略法律和文档工作
  17. 一个简单的迁移清单

为什么要自行托管 Google Fonts?

Google Fonts 让优秀的排版变得简单。添加一个样式表,选择几个字重,然后发布页面。多年来,这一直是小团队的合理默认选择。

代价是,每位访问者的浏览器都会联系第三方服务,以获取字体 CSS 和字体文件。这会带来两个后果。

首先,它给渲染增加了一个外部依赖。如果字体 CSS 很慢、被阻止,或在用户所在地区或网络中不可用,你的页面就会等待或回退。

其次,它带来了隐私问题。一次字体请求可能会向第三方暴露用户的 IP 地址、用户代理、referrer policy 上下文以及时间信息。Google Fonts 声明它不会通过 Fonts API 设置 cookie,但“没有 cookie”并不等于“没有个人数据”。在 GDPR 下,IP 地址在特定语境中仍可能属于个人数据。

自行托管字体并不是每个网站都自动必须做的事,本文也不是法律建议。但对于欧洲网站、公共部门网站、医疗、教育、金融,或任何试图减少不必要第三方请求的团队来说,本地托管通常是更干净的选择。

如果做得好,它通常也能带来性能收益。关键在于“做得好”。把六个字体文件复制到 /assets/fonts/,然后在每个页面上全部加载,可能比使用托管服务更糟。如果你想了解更广泛的性能背景,我们之前关于为什么 web fonts are still the easiest performance win on most sites 的文章介绍了常见的浪费模式。

自行托管后会发生什么变化

当你以常规方式使用 Google Fonts 时,页面会这样做:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">

浏览器会先从 fonts.googleapis.com 请求 CSS,然后从 fonts.gstatic.com 下载字体文件。

自行托管时,你的页面应当从自己的域名请求 CSS 和字体文件:

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

这会移除第三方字体请求。同时,你也需要负责选择文件格式、缓存头、回退字体以及更新。

这份责任值得认真对待。字体位于关键渲染路径上。糟糕的字体配置可能导致文本不可见、布局偏移以及首次渲染缓慢。

第 1 步:审计你实际使用的内容

在下载任何内容之前,先列出网站真正需要的字体家族、字重、样式和字符集。

一个典型的营销网站可能需要:

  • 正文使用 Regular 400
  • 标题和按钮使用 Semibold 600 或 bold 700
  • 只有在设计确实使用斜体时,才需要 Italic 400
  • 仅使用 Latin 字符集,除非网站支持更多语言

要警惕旧的设计系统默认值。许多网站加载 300、400、500、600、700、斜体以及多个文字系统,只是因为有人曾经在字体选择器中选中过它们。

在浏览器 DevTools 中打开 Network 面板,按“font”过滤,重新加载页面,然后检查请求了哪些文件。接着检查 CSS 中的 font-weight 使用情况。如果你的 CSS 从未使用 300,就不要托管 300。

如果你之后要评估影响,Lighthouse 可以提供帮助,但不要把它的分数当作全部事实。把它作为诊断工具,而不是裁判。我们有一份单独的指南,介绍如何 reading a Lighthouse report without panicking,在确定字体修复优先级时会很有用。

第 2 步:下载正确的字体文件

Google Fonts 提供开源字体。你可以从 Google Fonts 网站或相关字体项目仓库下载它们。请检查许可证,但大多数 Google Fonts 都根据 SIL Open Font License 或 Apache License 等开放许可证分发。

对于 Web,优先使用 WOFF2。现代浏览器广泛支持它,而且通常比 TTF 或 OTF 小得多。在 2026 年,直接向浏览器提供 TTF 对公共网站来说很少有充分理由。

一个合理的目录结构如下:

/public
  /fonts
    inter-latin-400.woff2
    inter-latin-600.woff2
    inter-latin-700.woff2

使用描述性文件名。六个月后,font.woff2 会很恼人。inter-latin-600.woff2 枯燥但有用。

如果你的网站使用构建系统,请把源字体放在清晰的位置,并让构建流水线将优化后的文件复制到公共资源目录中。

第 3 步:在适当情况下对子集化字体

子集化意味着移除你不需要的字符。一个完整字体可能包含 Latin、Cyrillic、Greek、Vietnamese、符号以及许多 OpenType 功能。如果你的纯英文落地页只需要 Latin 字符,子集文件可以小很多。

常见做法有两种:

  1. 使用字体提供方或仓库提供的预构建子集。
  2. 使用 fonttools 中的 pyftsubset 等字体工具生成自己的子集。

对许多团队来说,预构建的 Latin 子集已经足够。自定义子集适用于文本非常受限的页面,例如只有有限文本的单个活动页面,或字符覆盖范围可预测的产品 UI。

多语言网站要谨慎。缺失字形会导致混用回退字体,看起来可能像是出错,并损害可读性。如果你支持多种语言,应将字体子集映射到语言路由,而不是在所有地方强制使用一个很小的子集。

第 4 步:编写你的 @font-face 规则

一个最小化的本地配置如下:

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

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

这里有几个细节很重要。

对大多数内容型网站使用 font-display: swap。它会告诉浏览器先快速显示回退文本,然后在 Web 字体到达时进行替换。这可以避免最糟糕的 FOIT:不可见文本闪烁。

设置明确的回退字体栈。如果自定义字体加载失败,用户仍然应该看到可读的文本。回退字体不是事后补救;它们是设计的一部分。如果你需要重新审视字号、行长和正文文本选择,可以从 a practical guide to readable type on the modern web 开始。

正确匹配字重。如果你的 CSS 请求 font-weight: 500,但你只定义了 400 和 700,浏览器可能会合成一个中间字重。这并不总是很糟,但可能看起来不一致。

第 5 步:移除外部 Google Fonts 调用

添加本地字体 CSS 后,从模板中移除旧的远程调用。

查找:

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

还要检查:

  • CMS 平台中的主题设置
  • 页面构建器的排版面板
  • 第三方小组件
  • 标签管理器
  • 旧的 CSS 导入,例如 @import url('https://fonts.googleapis.com/...')

最后一项很常见。用于字体的 CSS @import 通常对性能更差,因为它会延迟发现。如果你自行托管,请在主 CSS 或较早加载的字体 CSS 文件中直接定义字体。

隐私工作经常失败,是因为团队修复了显眼的模板,却遗漏了脚本、小组件和旧嵌入。同样的模式也会出现在同意管理工作中;如果你正在更广泛地减少第三方接触面,我们关于 what changed for cookies in 2026 的指南会是有用的补充。

第 6 步:设置缓存头

字体文件是静态资源。如果文件名带有版本或内容哈希,就应该积极缓存它们。

一个良好的生产环境响应头是:

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

只有当文件变化时 URL 也会变化时,才使用长期 immutable 缓存。例如:

inter-latin-400.a8f3c2.woff2

或带版本的路径:

/fonts/v2/inter-latin-400.woff2

如果你在不改变 URL 的情况下覆盖 /fonts/inter-latin-400.woff2,一些用户可能会长时间保留旧文件。没出问题时这没关系,直到它出问题。版本化可以避免这个问题。

同时,请使用正确的 MIME 类型提供字体:

Content-Type: font/woff2

大多数现代托管平台会自动处理这一点,但仍值得验证。

第 7 步:只考虑预加载关键字体

预加载可以帮助浏览器更早发现重要字体:

<link rel="preload" href="/fonts/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>

请谨慎使用。预加载首屏主要文本字体,而不是每一种字重。过度预加载会与 CSS、图片和 JavaScript 竞争。

即使是同源字体,也要在字体预加载中包含 crossorigin。字体获取使用 CORS 模式,省略它在某些配置中可能导致重复下载。

如果你不确定,就测试。不要因为某个清单这么说,就照搬预加载。

第 8 步:测试隐私和性能

测试很直接。

打开 DevTools,在禁用缓存的情况下重新加载页面,并在 Network 面板中过滤:

  • fonts.googleapis.com
  • fonts.gstatic.com
  • .woff2
  • font

你应该看到字体文件来自自己的域名,并且没有 Google Fonts 请求。

然后分别用冷缓存和热缓存测试。首次访问时,字体应下载一次。之后访问时,它们应根据浏览器情况来自内存或磁盘缓存。

检查字体替换时是否发生布局偏移。如果标题跳动,说明你的回退字体度量与 Web 字体差异过大。你可以通过选择更接近的回退字体,或使用较新的 CSS 字体度量覆盖项来减少可见偏移,例如 size-adjustascent-overridedescent-overrideline-gap-override。这些更高级,但对打磨精致界面很有用。

最后,在隐私浏览模式或启用内容拦截器的情况下测试页面。自行托管的一个好处是,隐私工具不太可能意外阻止你的排版。

应避免的常见错误

托管过多字重

这是最常见的失败点。两个字重通常就够了。三个通常已经很充足。除非有充分理由,否则五个字重往往是设计系统异味。

忘记斜体

如果你的内容使用真正的强调,请加载真正的斜体文件。合成斜体可能看起来很差,尤其是在长篇编辑内容中。

保留旧的 Google CSS 链接

这会违背迁移的目的。迁移后,除非另一个组件正在注入,否则不应有任何字体请求发往 Google。

提供字体但没有长期缓存

自行托管给了你控制权。用好它。字体是长期缓存的理想候选。

忽略法律和文档工作

如果你的隐私政策之前提到过 Google Fonts 或第三方字体加载,请在迁移后更新它。如果你维护数据处理清单,也请同步更新。技术变更与合规记录应当一致。

<!-- tool-cta:start -->

💡 试试这个: 使用 Webfont Generator 将你从 Google Fonts 下载的 TTF 文件转换为可自行托管的 WOFF2 以及 CSS。

<!-- tool-cta:end -->

一个简单的迁移清单

  1. 列出你实际使用的字体家族、字重、样式和文字系统。
  2. 下载 WOFF2 文件并确认许可证。
  3. 如果网站语言需求有限,请对子集化字体。
  4. 添加带有 font-display: swap 的本地 @font-face 规则。
  5. 移除所有 Google Fonts 的 linkpreconnect@import 引用。
  6. 从自己的域名提供字体,并设置长期缓存头。
  7. 如果测试支持,只预加载最重要的首屏字体。
  8. 在 DevTools 中验证没有 Google Fonts 请求残留。
  9. 如有需要,更新隐私文档。

自行托管字体并不是什么光鲜的工作。它是一类小型基础设施清理,可以降低依赖风险,改善隐私保护态势,并让渲染更可预测。通常,这值得花上一两个小时。

常见问题

自行托管 Google Fonts 合法吗?
通常是合法的。大多数通过 Google Fonts 提供的字体都是开源的,并可根据各自许可证自行托管。上线前请始终检查具体字体的许可证。
自行托管字体会自动让我的网站符合 GDPR 吗?
不会。它只移除了一种常见的第三方数据传输。GDPR 合规取决于你更广泛的数据收集、同意机制、文档和供应商设置。但自行托管字体是一项实际的隐私改进。
我应该只使用 WOFF2 吗?
对于大多数现代网站,是的。WOFF2 具有广泛的浏览器支持和较强的压缩能力。TTF、OTF、EOT 和 SVG fonts 等旧格式现在很少需要。
本地字体总是比 Google Fonts 更快吗?
不一定。托管不佳的本地字体可能更慢。只有在使用小体积 WOFF2 文件、避免不必要字重、设置适当缓存头,并从快速基础设施提供字体时,本地托管效果最好。
我如何知道 Google Fonts 是否仍在加载?
打开浏览器 DevTools,重新加载页面,并在 Network 面板中检查是否有对 `fonts.googleapis.com` 或 `fonts.gstatic.com` 的请求。同时搜索模板和 CSS 中是否仍有旧的 Google Fonts 链接或 `@import` 规则。

来源与进一步阅读

  1. MDN Web Docs: @font-face
  2. web.dev: Optimize webfont loading and rendering
  3. Google Fonts FAQ
  4. Regulation (EU) 2016/679: General Data Protection Regulation
关于作者
The Wux Webtools Team

最后更新:

继续阅读