网页加载速度之中文字体优化篇

不久前我们介绍了《Google Analytics跟踪网站页面速度》,其中我们提到了对网页字体的优化可以增加网页加载性能。那么本篇我们将展开讨论如何优化网页字体来获得最佳的表现。由于中文字体的文件少则几兆多则十几兆,对于Web-font来说可操作性不强,我们将先说说英文字体。文章的后面部分再回到中文字体的解决方案。
TL;DR
为了避免太枯燥的阅读,如果你不是前端工程师或者是前端技术爱好者,那么仅仅需要把下面五点建议发给您的小伙伴。
- 在服务器开启HTTP/2,并对静态资源设置E-TAG和Cache-Control。
- 避免使用Google Fonts,将字体文件放在国内可以访问的CDN或者本地。
- 使用<link rel=preload>来提前加载字体文件。
- 在@font-face中,使用font-display: swap避免字体阻止期中的空白文本。
- 在@font-face中,使用unicode-range获取所需的中文字体片段。
网页加载中的字体加载过程

网页加载的过程大致是一个画画的过程。当开始构思时,画家会构思一个主题(对网页的HTTP请求),然后会对这个主题(HTML)所需要的元素(DOM 元素)进行填充和布局(DOM树)。对每个元素,画家要决定怎么画(获得CSS,并把CSSOM树与DOM树合并),上什么颜色(假设是CSS中的字体)。所有这些都齐了以后,画家就可以把画画出来了。
那么这里又有一个微观的过程就是上色的时间线(字体显示时间线):
字体阻止期 – 字体交换期 – 字体失败期
- 阻止期中,画家在找颜料(字体资源),这段时间画家不会上色。因此字体并不会显示。阻止期各个浏览器的默认定义不同,一般是3秒。这段时间如果找到颜料,那么阻止期就会结束,正常上色。如果超时未找到颜料,那么就会进入字体交换期。
- 交换期中,画家依然会在找颜料。不过画家会开始用备用颜料上色了。比如找不到蓝色,那么就用宝蓝代替。在这段时间里如果画家找到了颜色,那么会放弃宝蓝,用蓝色再上一次,所谓的“交换”。
- 失败期中,画家会接受找不到颜料的事实。用备用颜料上色。
我们从上面的字体显示时间线可以看出,要避免的是过长的阻止期,因为这段时间文字不会显示!另外对于一些公司的Logo用特定字体显示的情况,我们希望能够早点画出正确字体的文字,因此需要优化字体载入的时间。我们下面先讲优化字体载入时间。
利用<link rel=preload>提前加载字体文件
我们从画画的过程中可以看到,画家决定使用那种颜色是后面考虑的问题。但是如果我们预先在主题构思的时候想到这一点就可以提前去加载这个字体文件。

这样我们就可以把<link rel=preload>放到HTML的<head></head>中,让浏览器提前下载字体文件,而不用等DOM树完成后等CSS下载后才去请求。由于下载字体使用了额外的HTTP请求,因此HTTP/2可以大幅提高性能,它不需要受六个并发HTTP请求的限制。
具体的写法如下:
<link rel=”preload” href=”your-font.woff2” as=”font” type=”font/woff2” crossorigin>
当你在服务器上设置好E-TAG(告诉客户端你的资源有没有变化)和Cache-control(告诉客户端缓存时间长度)后,这些字体资源就不需要多次下载,以节省时间。
当然,不要忘了,部署preload的同时,你还可以把对字体的引用放入HTML中的inline CSS中。这样不用等CSS文件下完浏览器就知道需要请求这个资源了。
使用font-display: swap;控制字体阻止期
在CSS的@font-face规则中,你可以添加font-display: swap;语句来对字体的阻止期进行控制。默认是auto,与block近似。而改为swap后,意味着阻止期为0,而交换期为无限长。
这样一来你便可以避免网页出现空白文本,而立即用替换字体显示内容,一旦需要的字体下载完成后就可以替换原来的字体正确显示。
中文字体的优化
中文字体通常不建议让用户特别去下载字体文件,而是使用用户本地已有的字体文件,如宋体、黑体等。
另外,上面提到了所谓的替换字体,你可以在font-family中设置。比如
font-family: ‘microsoft yahei’, sans-serif;
浏览器会根据这个先后顺序来选择匹配字体。在上面的例子中,如果雅黑不可用,那么会用万能字体sans-serif来代替。如果你希望英文字符使用别的字符那么可以在雅黑前面加上。
虽然不特别添加中文字体可以正常显示中文,但是你还是需要添加中文字体的。比如下面这个例子,这两个字的Unicode都是U+5C06。如果你不指定中文字体就会出现爪字头的,而不是夕字头的将。同样的还有其他字比如“写”,下面的“与”的一横会出头。

如果你必须使用“正常人”电脑里不会安装的字体,那么你可以考虑使用unicode-range,这样做的好处是你不需要下载几个M的字体文件,而只需要把用到的加载进来。比如下面是基本汉字集的片段:
unicode-range:U+4E00-9FA5;
国内也有Web Font供应商提供这些云服务,也需要把文字预先提交生成特定的字体片段文件。
总结+参考资料
本篇我们介绍了一些基本的优化网页字体性能的手段,希望对你有所帮助。一些在开发中的Font-API我们没有涉及。我们参考了下面几篇文章,你可以扩展阅读。
《Web Performance Made Easy: Google I/O 2018 edition》
《CSS unicode-range特定字符使用font-face自定义字体 – 张鑫旭》
最后这里有Web Font Recipes repo,Zach Leatherman做的一些Demo。你可以在Chrome开发工具中用低网速来进行演示。