跳转到主要内容

按字分片:cn-font-split

适合谁看:内容不固定(博客、社区、电商),想把整款中文字体拆成很多小片、按需加载的开发者。

分片和子集的区别

  • 子集:只留下一部分字,其他字不要了。
  • 分片:一个字也不丢,把整款字体切成很多片,每片几十 KB,用 unicode-range 标明范围。页面用到哪些字,浏览器就只下载那几片。

文风网页字体用的就是分片,见《性能:子集、字体显示策略和预连接》。自己部署时,可以用开源工具 cn-font-split 生成同样的结构。生成同样的结构[1]。

cn-font-split 简介

cn-font-split 是「中文网字计划」使用的分片工具,Apache-2.0 许可。许可[2]。它会:

  • 按字符使用频率和字体内容分组,生成一批 WOFF2 分片;
  • 生成一份 CSS,里面是多条 @font-face,每条带 unicode-range[3];
  • 可选生成预览图和测试页面。

用法示例(Node.js)

npm install cn-font-split
import fs from 'fs';
import { fontSplit } from 'cn-font-split';

const input = new Uint8Array(fs.readFileSync('./LXGWWenKai-Regular.ttf').buffer);
await fontSplit({
  input,
  outDir: './dist/font',
  css: { fontFamily: 'My WenKai', fontWeight: '400' },
});

参数以官方文档为准,版本更新时可能变化。它还提供命令行、在线切割页面和前端构建插件。

分片后怎么用

  1. 把输出目录整个放到网站上(或对象存储),保证跨域头和缓存头正确;
  2. 在页面里引入生成的 CSS;
  3. 在样式里写 CSS 里声明的 font-family 名字和备用字体。

多个字重要分别切,每个字重一份 CSS。这几份 CSS 的 font-family 用同一个名字,font-weight 各不相同,写法见《写对 @font-face:字体名、字重和 local()》。

分片的代价

  • 请求数变多。HTTP/2 和 HTTP/3 下影响不大;
  • 同一个词的几个字可能落在不同分片里,先后到达时会看到字逐个替换;
  • 跨分片的连字、上下文替换可能失效,这对中文影响较小,对西文连字、阿拉伯文等影响较大。

参考资料

参考资料(3)
    1. cn-font-split 源码与文档:源代码与文档,GitHub:KonghaYao
    https://github.com/KonghaYao/cn-font-split中文网字计划 中文网字计划:https://chinese-font.netlify.app/MDN:unicode-range(英文) MDN:unicode-range:https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face/unicode-range