Skip to content

fix: load Google Fonts non-blocking (prevent blank page where the CDN is blocked)#33

Merged
study8677 merged 1 commit into
mainfrom
fix/nonblocking-fonts
May 22, 2026
Merged

fix: load Google Fonts non-blocking (prevent blank page where the CDN is blocked)#33
study8677 merged 1 commit into
mainfrom
fix/nonblocking-fonts

Conversation

@study8677
Copy link
Copy Markdown
Owner

Problem

The homepage <head> loads Google Fonts via a render-blocking <link rel="stylesheet" href="https://fonts.googleapis.com/...">. Where that host is throttled / null-routed (mainland China), the request hangs for tens of seconds and the browser holds back first paint — the page is fully blank even though the JS bundle loaded and React mounted. This matches a reported white screen (PC Chrome, China + VPN, fully blank, other overseas sites fine).

Fix (frontend/index.html)

Load the webfont stylesheet non-blocking: media="print" onload="this.media='all'", with a <noscript> blocking fallback for crawlers / no-JS clients. The page paints immediately with system fallback fonts and upgrades to the webfonts once (if) they arrive.

No JS/CSS bundle change — index-*.js hashes unchanged.

…DN is blocked

A render-blocking <link rel="stylesheet"> to fonts.googleapis.com holds back
first paint until the request resolves. Where that host is throttled or
null-routed (mainland China), the request hangs for tens of seconds and the
page stays fully blank even though the JS bundle loaded and React mounted.

Switch to a non-blocking load (media="print" + onload="this.media='all'") with
a <noscript> blocking fallback for crawlers, so the page paints immediately
with system fallback fonts and upgrades to the webfonts once (if) they arrive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@study8677 study8677 merged commit 388cad4 into main May 22, 2026
3 checks passed
Copy link
Copy Markdown
Owner Author

Code Review — fix/nonblocking-fonts

Language: HTML · File changed: frontend/index.html (+7 / -1)


总体评价

这是一个精准、有据可查的性能修复,使用了业界标准的非阻塞字体加载技术(web.dev / Lighthouse 推荐)。变更范围极小、目标明确,建议 Approve 合并


问题清单

级别 文件 & 行号 描述 建议
🟡 建议 index.html<link media="print"> + <noscript><link> Google Fonts URL 被复制了两次。若字体族或字重发生变化,需同步修改两处,容易遗漏。 可在注释旁标注 "两处 URL 须保持同步",或考虑用 CSS 变量 / 构建脚本统一管理字体 URL。
🟢 优化 index.html<link rel="preconnect"> 目前 preconnect<link> 加载前已建立连接,方向正确。但若 fonts.googleapis.com 在目标区域被屏蔽,preconnect 本身也会挂起(虽然不阻塞渲染)。 可考虑对 preconnect 也加 crossorigin 属性一致性检查;长远方案是将字体文件自托管(self-host),从根本上消除对 Google CDN 的依赖。
🟢 优化 index.html<noscript> <noscript> 保留了阻塞式加载,适用于无 JS 客户端和爬虫。现代 Googlebot 已支持 JS,但 Baidu、Bing 部分爬虫不执行 JS,保留 <noscript> 是正确决策,无需改动。

亮点

  • 注释质量极高:清楚说明了 media="print" → onload → media='all' 的工作原理、适用场景(中国大陆 CDN 封锁)和 <noscript> 的用途,符合项目"仅在 WHY 不明显时写注释"的规范。
  • 最小变更原则:仅修改 1 个文件、1 行核心代码,附加 6 行增量,风险极低。
  • display=swap 已就位:字体 URL 中已包含 display=swap,与非阻塞加载模式配合,确保回退字体立即可见,视觉 FOUT 可控。

修改示例(可选 — DRY 改进)

若担心 URL 双写维护问题,可在 HTML 注释中标注:

<!-- FONT-URL: update BOTH the <link> below and the <noscript> copy if fonts change -->
<link rel="stylesheet"
      href="`https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap"`
      media="print" onload="this.media='all'">
<noscript>
  <!-- FONT-URL duplicate (for no-JS crawlers) -->
  <link rel="stylesheet" href="`https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap"&gt;`
</noscript>

或长远方案:将字体文件下载到 frontend/public/fonts/ 并通过 @font-face 自托管,彻底解除对 Google CDN 的依赖。


Review generated post-merge for audit trail. No blocking issues found.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant