本站采用的字体可以通过 F12 开发者工具中查看。

font-family: "Noto Serif SC", Georgia, serif, -apple-system, PingFang SC, "Apple Color Emoji", "Segoe UI Emoji";

其中 -apple-systemPingFang SC 分别为苹果系统下的英文字体和中文字体(苹方),Noto Serif SC思源宋体,这是一款由 Google 和 Adobe 共同开发的开源字体,Google 方面取名为 Noto Serif, SC 表示 Simplified Chinese, 并对字体作了一些修改。而 Adobe 方面取名为 Source Han Serif. 两个字体的观感大体上一致。最后面两个字体是为了提供 emoji 支持。

字体加载顺序

一般来说,英文字体在应该放在中文字体之前,因为中文字体中的英文字符观感上通常没有英文字体中的好,而如果先匹配中文字体就会导致网站使用中文字体中的英文字体。而 Noto Serif SC 中的英文字体还不错,所以本站会直接尝试匹配 Noto Serif SC 字体并在本地无字体时尝试从服务器下载,在下载完成前,字体 fallback 为衬线字体 Georgiaserif, 并在下载完成后 swap 回来(参见 css 中的 font-display 参数)。

通过字体包分割加速字体加载

中文字体动辄几十上百 MB 的大小相较于英文字体几十 KB 的大小注定很难直接在网页上应用,一来浪费资源,二来加载时间长。本站采用字库分割的方法加载中文字体。即将字库根据 Unicode 编码分为多个范围(多个字体文件),渲染 Html 时按需加载指定范围的字体。

  1. 安装 google-font-splitter,需要环境 nodejs 12+.
     
  2. 根据 Github 上的 README 教程从 Google Fonts 选择一款字体(这也是为什么本站采用 Google 版本而非 Adobe 版本)并通过该命令行工具下载其字库分割文件。下载后将得到一个以字体名称命名的目录,以我的字体 noto-serif-sc 为例,结构如下

    noto-serif-sc
    ├── noto-serif-sc.css
    └── s
     └── notoserifsc
         └── v22
             ├── H4chBXePl9DZ0Xe7gG9cyOj7kqGWbg.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.100.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.101.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.102.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.103.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.104.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.105.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.106.woff2
             ├── H4chBXePl9DZ0Xe7gG9cyOj7oqP0dTpxZbB9E9gjjmzKvaeKHUTtJDWv3z-us4bxD8F5og.107.woff2
             ...

    可以看到字体文件被分割为了大量的 woff2 字体文件,而其中 noto-serif-sc.css 文件包含 css 中的 @font-face 定义,用于把字符 Unicode 范围映射到指定的字体文件 URL.
     

  3. 在项目中引用生成的字体 css 文件。可以参考上述 Github 项目中的方式在 Vue 等框架中引用。
    在 Html 中引用:

    <link href="css 文件 URL" rel="stylesheet">

    在其它 css 文件中引用:

    @import url("css 文件 URL");

    对于本站使用的 Typecho 框架 + Cuckoo 主题,可以在后台设置的“高级设置-字体 css 链接中填入上述 css 文件 URL”
    font-setting.png
     

  4. 设置 font-family
    根据个人喜好设置字体匹配顺序,一般把英文字体放在前面

效果

到这里就完成了分段加载中文字体的优化。看看效果。
font-loading.png
可以看出字体文件被分割为了数个几十 KB 大小的文件加载,并且可以被 Pipelined.

参考资料

[1] 前端页面性能优化 - 字体加载优化
[2] google-font-splitter