这类问题我又碰上了一次。为了压缩体积,主字体做了子集化,只保留常用三千五百字。上线后技术文章里的生僻字和日文假名全变成方框,Safari 上尤其明显。字体文件从 3.2MB 降到 180KB,LCP 好看了,内容却读不了。

第一反应是「font-display 设成 swap,回退字体也没有对应字形」,验证下来不成立。

把日志和配置对完,能解释这个现象的基本就这几处。子集化脚本按一份固定的常用字表切分,没有扫全站实际用字;多语言页面复用同一份中文字体子集,假名和注音符号全缺;缺字时没有回退到系统字体,浏览器只能画方框。

先统计页面上实际出现的字符集

curl -s https://www.example.com/p/1024 | python -c "import sys;print(len(set(sys.stdin.read())))"

随后按全站正文重新生成子集,带上技术符号与多语言字符

pyftsubset font.ttf --text-file=chars.txt --flavor=woff2

给字体栈补上系统回退,缺字时不至于全是方框

font-family:"SiteFont","PingFang SC","Microsoft YaHei",sans-serif;

剩下的就是抽十个含生僻字的页面逐一核对

curl -s https://www.example.com/p/1024 | grep -c '□'

改完先别撤,确认这几项。生僻字和假名都能正常显示,字体体积控制在 300KB 以内,首屏时间没有明显回退。

补一句。子集化要按真实语料做,凭经验挑字表一定会漏,宁可多带两千字,也别让读者看到方框。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189