中文字体子集化之后首屏少了 900KB
引入一款想用的中文字体,woff2 文件 10.6MB。首屏字体请求把渲染堵了将近两秒。
中文字库大是因为字符多,常用汉字三千上下,全量收录是两万多。而一个博客实际用到的字符,把历史文章里出现过的全收集起来,也就一千多个。
子集化就是只保留用到的那些:
pyftsubset font.ttf \
--text-file=used-chars.txt \
--flavor=woff2 \
--output-file=font-subset.woff2
10.6MB 变成 380KB。加上 font-display: swap,首屏不再等字体:
@font-face {
font-family: 'Brand';
src: url('/fonts/brand-subset.woff2') format('woff2');
font-display: swap;
}
代价有三个,都得记着。
新字会掉字体。子集里没有的字符(用户昵称里的生僻字、以后写的文章里的新字)会退回默认字体,一句话里混两种字形,很难看。我的处理是保留一份系统字体栈,并且每次发新文章后重新生成一次字符表——这一步必须自动化,手工做一定会忘。
font-display 的三种行为要想清楚。swap 是先用后备字体显示、加载完替换,会有一次跳字;block 是短暂不可见;optional 由浏览器决定,可能整个页面生命周期都不换。我把标题设 optional、正文设 swap,因为标题跳一下影响不大,正文不能空白。
数字和标点也要在子集里。第一版我漏了破折号和书名号,页面上出现方框。
另一处省下来的:图片。首屏那张封面从 480KB 的 jpg 换成 webp 是 60KB,比字体那一千多 KB 更容易做到。优化顺序应该是"体积最大的先动",而我是先啃了字体。