独立托管 Web 字体

2023-02-21 ⏳4.6分钟(1.8千字) g

本站使用霞鹜文楷字体,最早还是在班班的频率1博客上看到的,非常喜欢。本站最早使用 CDN 加载该字体。但因为 jsDelivr2 在国内日益不稳定,我最近决定用自己的服务器独立托管霞鹜文楷。本文就梳理这其中的来龙去脉。

最近发现 elemecdn 上有霞鹜文楷的镜像3,加载速度很快。大家可以考虑使用。

因为字体相关的请求实在太多,本站已经切换到 elemecdn。

通常浏览器只能使用系统自带的字体渲染文字。因为不同的系统安装的字体也不尽相同,所以相同的页面在不同的浏览器下显示效果也有不少差异。于是就诞生了 Web 字体,也叫网页字体。

Web 字体的基本思想是让浏览器从网络上自动下载需要的字体,然后再渲染文字。这不但可以统一网页在不同系统上的展示效果,还可以让设计师随心所欲地使用各种字体来表达情感。

但是,这么美好的东西在汉字文化圈却遇到了不小的麻烦。因为拼音文字一般只很少的字母(比如拉丁字母有二十四个),再加上部分标点符号和大字形式,它们的字体文体通常都不大。但常用汉字就有三四千,如果再加上几种主要的字体,那单个字体文体可能会达到几兆甚至几十兆字节之巨,很难应用到 Web 字体领域。也正因如此,汉字圈的 Web 字体发展比较迟缓😂

但我打开频率网站的时候发现它的字体加载速度奇快无比,就非常纳闷。一番研究后发现,原来 Web 字体支持 unicode-range4 属性。简单来说我们可以将一个大的字体文件拆分成多个小文件,每个文件对应一组 @font-face 再用 unicode-range 指定文件的字符范围。比如下面的一段字体声明:

@font-face {
  font-family: 'LXGW WenKai Lite';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./files/subset-4.woff2') format('woff2');
  unicode-range: U+1f1e9-1f1f5
}

浏览器在渲染文字时如果碰到了1f1e9-1f1f5范围内的 Unicode 字体才会下载对应的文件。这样就在一定程度上解决了单个中文字体体积过大的问题。所以班班的网页字体加载很快。

霞鹜文楷是一款开源字体5,基于日本的 Klee One 字体。该项目的主要工作是添加其中缺失的汉字6,并不关注 Web 字体等衍生技术。好在 Chawye Hsu 创建了专门的项目7来支持 Web 字体。

这里最主要的工作就是划定字体拆分规则,然后生成对应的字体文件和 CSS 描述文件。 Chawye 将生成后的文件托管到 jsDelivr8 上。因为字体和 CSS 文件比较多,所以就直接使用 jsDelivr 上的版本。

但为什么又要自行托管呢?萌生此想法的直接原因是有一次打开博客感觉字体加载很慢。的确,自从 jsDelivr 的 ICP 备案过期后就大不如从前了。而且随着 Web 技术的发展,使用 CDN 的优势也越来越不明显。

曾经使用 CDN 加载公共静态资源是标准做法,因为同样一个 js 库(比如 jQuery),很多网站都在用。如果网络甲跟乙都使用相同版本的 jQuery,那么用户先访问甲网站之后再访问乙网站就不需要重复加载 jQuery。

但这种方式有几个问题。第一,就是公共库通常都有多个版本,而不同网站使用相同版本且在相同的 CDN 服务的概率比较小。所以加速效果有限。第二,现在的浏览器都支持 HTTP/2 协议,该协议可以通过复用底层 TCP 连接降低加载耗时,但使用三方 CDN 就必须创建新的 TCP 连接。第三,也是最重要的一点,使用共享 CDN 资源可能会泄漏用户隐私!

我开始也不太理解怎么能泄漏隐私呢?看了这篇文章9算是大致明白了。

假设黑客得知某网站A使用公共 CDN 加载某静态资源。他可以在自己的网站上也加载相应的资源,然后引诱用户访问自己的网站。如果用户访问了,就通过脚本下载前面说的静态资源。如果加载时间小于某个阀值则证明该用户曾经访问过网站A,这就泄露了用户的隐私。

因为有隐私风险,所以浏览器厂商引入了 partitioning the cache 也就是分区缓存。简单来说就是对于相同的资源,不同的网站使用不同的缓存。也就是说,虽然网站 A 和 B 都依赖相同 CDN 上的某个资源,但用户访问 A 所加载的资源并不能在访问 B 时使用。也就说,相同的 CDN 资源对不同的网站来说就是不同的资源,根本不能实现加速的效果。

结合分区缓存以及前两个问题,再加上 jsDelivr 时不是抽风,所以我决定自己独立托管 Web 字体。因为我的网站也开启了 HTTP/3 所以加载速度应该不会差太多,而且更稳定。唯一的问题是需要消耗额外的流量。但我的虚拟主机每月都剩余很多流量,不用白不用。

以上就是本文的全部内容。我们可以看到,随着技术的更新,很多曾经的最佳实践已经不再必要甚至变成了负优化,所以技术人要持续学习,不断适应新的环境。