Advanced (更新: 2026/6/2)

使用 Claude Code 优化 Web 字体的实战指南

用 Claude Code 安全优化 Web 字体:preload、font-display、子集化、CLS/LCP 与验证流程。

使用 Claude Code 优化 Web 字体的实战指南

字体优化首先是渲染稳定性问题

Web 字体不只是视觉风格。加载策略错误时,页面会出现空白文字、标题突然换行、按钮位置跳动,甚至让 LCP 变慢。LCP 是 Largest Contentful Paint,意思是首屏最大内容元素完成显示所需的时间。CLS 是 Cumulative Layout Shift,意思是页面元素在加载过程中发生的意外位移。中文、日文、韩文等大字符集字体通常更重,所以一个字体文件就可能拖慢首屏。

这篇文章以 Astro 网站为例,说明如何让 Claude Code 安全地实现字体优化。我们会覆盖加载策略、preloadpreconnectfont-display、可变字体、字体子集化、自托管和第三方字体的取舍、CLS/LCP 风险、Lighthouse 与 WebPageTest 风格的检查,以及可以直接复制给 Claude Code 的提示词。

事实性判断以官方文档为准。MDN 解释了font-display的不同模式,也说明了rel="preload"中字体资源需要正确声明类型和跨域属性。整体最佳实践可以参考 web.dev 的字体最佳实践Web 字体优化以及Web Vitals

先决定加载策略,再让 Claude Code 改代码

不要直接说“帮我优化字体”。这样的指令太宽,Claude Code 可能会到处加preload,或者删除设计中仍然需要的字重。先回答三个问题:首屏必须显示哪些文字,品牌字体是否真的必须用于正文,哪些字体可以延后或删除。

场景推荐策略好处常见失败
多语言博客正文正文先用系统字体,标题使用子集化 Web 字体即使字体慢,读者也能立即阅读把标题字体误用到全文
SaaS 控制台自托管 Inter 等拉丁可变字体多个字重可由一个文件覆盖未使用的斜体、轴或语言范围仍被打包
营销落地页首屏只预加载 LCP 标题实际使用的 WOFF2首屏销售文案更早出现把所有字重都预加载,抢走图片带宽
旧 icon font改成 SVG 或组件图标减少一个字体请求伪元素样式没有同步迁移

博客页面通常不需要全文强制使用 Web 字体。正文越长,越应该先保证可读性,再把品牌感留给标题、导航或 CTA。SaaS 管理界面则不同,它通常有大量数字、标签和按钮,使用一个拉丁可变字体更容易统一视觉。落地页要把字体和 hero 图片一起看,因为两者都会影响首屏。相关图片策略可以参考Claude Code 图片优化指南,整体速度优化可以继续看Claude Code 性能优化

在 Astro 中实现 preload 和 preconnect

preload是很强的浏览器提示,只适合首屏一定会用到的一两个字体文件。不要把所有字重、所有语言、滚动后才出现的字体都预加载。自托管字体时,通常不需要preconnect。使用 Google Fonts 等第三方服务时,才需要考虑对 CSS 域名和字体文件域名预连接。

---
// src/layouts/BaseLayout.astro
const criticalFonts = [
  { href: "/fonts/inter-var-latin.woff2", type: "font/woff2" },
  { href: "/fonts/noto-sans-jp-latin-kana.woff2", type: "font/woff2" },
];

const usesGoogleFonts = false;
---

<html lang="zh">
  <head>
    {criticalFonts.map((font) => (
      <link rel="preload" href={font.href} as="font" type={font.type} crossorigin />
    ))}

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

    <link rel="stylesheet" href="/styles/fonts.css" />
  </head>
  <body>
    <slot />
  </body>
</html>

审查时看三点。第一,href必须和@font-face里的src一致。第二,as="font"type="font/woff2"crossorigin要齐全。第三,被预加载的字体必须在首屏很快使用。如果浏览器提示“preloaded but not used”,应该减少预加载,而不是忽略警告。

font-display 需要和回退字体一起设计

font-display: swap会先用回退字体显示文字,然后在 Web 字体到达后替换。它可以减少不可见文字,但如果回退字体和目标字体的宽度、行高差异太大,替换时仍然会造成 CLS。optional适合不关键的正文或弱网场景,因为浏览器可以选择继续使用回退字体,而不是很晚才替换。

/* public/styles/fonts.css */
@font-face {
  font-family: "InterVariable";
  src: url("/fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "NotoSansJPSubset";
  src: url("/fonts/noto-sans-jp-latin-kana.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+3000-30FF, U+FF00-FFEF;
}

@font-face {
  font-family: "InterFallback";
  src: local("Arial");
  size-adjust: 107%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}

:root {
  --font-ui: "InterVariable", "InterFallback", system-ui, sans-serif;
  --font-ja: "NotoSansJPSubset", "Hiragino Sans", "Yu Gothic", sans-serif;
}

body {
  font-family: var(--font-ui);
}

article {
  font-family: var(--font-ja);
}

MDN 的unicode-range说明了如何让一个@font-face只负责部分字符范围。注意,它不会自动让文件变小。想减少字节,仍然要生成更小的 WOFF2 文件。

用可变字体和子集化减少字节

可变字体可以用一个文件覆盖多个字重,适合按钮、导航、表格和管理后台等 UI。它不一定总是更小。如果包含很多轴、斜体或语言范围,文件仍然可能很大。让 Claude Code 先统计真实使用的字重和脚本,再决定是否替换。

子集化是把字体中暂时不需要的字符移除。它适合首屏标题、导航、固定 CTA 和拉丁/假名范围。对正文使用时要谨慎,因为新文章可能引入子集中没有的字符,结果页面会混用多种字体。

# Create a WOFF2 subset with Latin, punctuation, kana, and full-width forms.
python -m pip install "fonttools[woff]"
mkdir -p public/fonts

pyftsubset ./vendor-fonts/NotoSansJP-Regular.ttf \
  --output-file=./public/fonts/noto-sans-jp-latin-kana.woff2 \
  --flavor=woff2 \
  --layout-features='*' \
  --unicodes="U+0000-00FF,U+3000-30FF,U+FF00-FFEF"

这个命令故意不包含大部分汉字。它适合标题、导航和固定文案,不适合完整正文。如果要覆盖正文,需要从 MDX 或模板中抽取实际字符,生成--text-file,或者准备单独的汉字子集。还要检查字体许可证,确认自托管、修改和再分发都被允许。

自托管和第三方字体的取舍

自托管的优势是 URL 稳定、缓存可控、preload目标明确、子集化自由。代价是你要维护文件、许可证、更新和构建脚本。第三方字体上线快,但会增加外部连接和 CSS 请求,并且实际字体 URL 可能由提供方 CSS 决定。

判断点自托管第三方
连接只访问本站需要 DNS、TLS、CSS 域和字体域
缓存可以使用文件指纹和长期缓存依赖提供方响应头
子集化可完全控制取决于服务能力
运维责任更多上手更快但外部依赖更多

性能敏感页面通常把首屏关键字体自托管,装饰字体延迟加载。快速原型可以使用第三方字体,但要使用display=swap,只连接必要域名,只加载实际使用的字重。不要同时保留 Google Fonts CSS 和自托管 CSS,否则浏览器可能下载两套字体。

用 Lighthouse 和 WebPageTest 风格检查结果

优化完成后,不要只看页面有没有变好看。Lighthouse 可以给出 LCP、CLS 和字体显示相关提示。然后用浏览器网络面板或 WebPageTest 的思路看瀑布图:HTML、CSS、关键字体、hero 图片和 JavaScript 的顺序是否合理。

URL="https://example.com/"
npx --yes lighthouse "$URL" \
  --only-categories=performance \
  --chrome-flags="--headless" \
  --output=json \
  --output-path=./lighthouse-fonts.json

node -e "const r=require('./lighthouse-fonts.json'); for (const id of ['largest-contentful-paint','cumulative-layout-shift','font-display']) console.log(id, r.audits[id]?.displayValue ?? r.audits[id]?.score ?? 'n/a')"

检查瀑布图时,关键字体应该早开始,但不能阻塞首屏 CSS 或图片。重复访问时字体应该来自缓存。同一个 WOFF2 不应下载两次。慢速移动网络下,正文应立即可读。字体替换时标题、价格、按钮和广告位不能跳动。

常见坑包括:预加载了首屏没有使用的粗体;迁移到自托管后忘了删除 Google Fonts CSS;只加了font-display: swap却没有调整回退字体;子集中漏掉全角数字、标点或长音符号;把 icon font 当成普通文字字体继续预加载。

给 Claude Code 的安全提示词

先让 Claude Code 只审计,不要编辑。

Audit web font loading in this Astro site. Do not edit files yet.

Find:
- @font-face, Google Fonts, Fontsource, and CSS import locations
- Font files used above the fold
- preload and preconnect hints that are missing or unnecessary
- CLS or LCP risks caused by font swapping
- Candidates for self-hosting, variable fonts, and subsetting

Return:
- A prioritized table of changes
- Files that should be edited and files that must not be touched
- Verification commands and residual risks

确认方案后,再限制编辑范围。

Implement web font optimization only in these files:
- src/layouts/BaseLayout.astro
- public/styles/fonts.css
- generated files under public/fonts/

Acceptance criteria:
- Preload only WOFF2 files used in the first viewport
- Do not add preconnect when fonts are self-hosted
- Every @font-face has a deliberate font-display value
- Fallback metrics are adjusted to reduce CLS
- Existing routes, article slugs, hero images, and unrelated content are untouched

Verification:
- npm run build
- node scripts/check-code-fences.mjs
- Lighthouse check for LCP, CLS, and font-display
- Report what could not be verified

实际验证结果和 CTA

Masa 的实际经验是,明确“只预加载 LCP 标题使用的字体,正文保持系统字体可读”比笼统要求“优化字体”更稳定。日文内容页中,先加载拉丁和假名子集后首屏更稳,但正文完整覆盖仍需要字符抽取流程。最终最有价值的检查不是单个 Lighthouse 分数,而是慢速移动网络瀑布图加上人工观察标题和 CTA 是否跳动。

如果要把这套做法放进团队流程,请把字体规则写入CLAUDE.md。可以先用免费速查表固定安全命令,再用产品模板整理提示词和审查清单。需要把 Core Web Vitals、文章质量和收益 CTA 一起改善时,可以看Claude Code 培训与导入咨询

发布前自检:本文包含 3 个以上实际用例、Astro/CSS/bash 示例、官方 MDN 和 web.dev 外部链接、内部链接、具体失败模式、自然 CTA,以及实际验证结果说明。

#Claude Code #Web 字体 #Core Web Vitals #Astro #性能优化
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。