文章 · 性能优化

用 unicode-range 给中文可变字体做按需加载

中文字体的问题是「字多」。常用汉字三千个起,一套完整字库轻松十几兆,整包丢给浏览器,首屏还没渲染完字体就先卡住了。unicode-range 的思路是把字库按 Unicode 区间切开,浏览器只下载页面上真正用到的那些分片。

先量清楚要付多少流量

一份 12MB 的思源黑体整包,在 4G 网络下要跑三到五秒。而首屏真正出现的汉字往往不到两百个,为了这两百个字付十几兆的代价,显然不划算。

按 Unicode 区间切片

unicode-range 是 @font-face 的描述符,用来声明「这一片只负责这些码位」。把字库按区间切成一百多个小文件后,浏览器解析 CSS 时就能算出页面实际用到的码位,只拉命中那几片。

css
@font-face {
  font-family: 'SourceHanSans';
  src: url('hans-012.woff2') format('woff2');
  unicode-range: U+4E00-4E7F;
}

顺便把字重也收掉

切片之后还有一层浪费:字重。中文可变字体一个文件就能覆盖 100 到 900 整个区间,比每个字重单独打包省得多。两者叠加时记得让切片区间保持一致,否则浏览器的字体匹配会反复回退,反而更慢。

首屏字体流量从 12MB 降到 240KB,FCP 提前了 0.9 秒。

评论9

访客

登录后参与评论,你的发言会署上自己的名字。

  • 123

    123@12026-10-22

    测试

  • 许原

    许原作者@xuyuan2026-10-12

    放在最前面:看到都会回,先谢过各位补充的经验。

  • 沈亦

    沈亦@shenyi2026-10-14

    预留尺寸这一步收益比我想的大,页面重排少了以后体感差别很明显。

  • 韩雪松

    韩雪松@xuesong2026-10-15

    有没有考虑过体积之外的因素?我们这边的瓶颈其实在解码那一步。

  • 何知白

    何知白@hezhibai2026-10-16

    中文按需加载这块终于有人把量化的过程写出来了,之前看到的都只给结论。

  • 苏晚

    苏晚@suwan_dev2026-10-17

    我们也是这么做的,唯一想补充的是切片之后记得把字体文件放到带长缓存的路径上。

  • 顾青

    顾青@guqing2026-10-18

    对,缓存头配错的话每次访问都会重下,前面省下的全还回去了。

  • 郑一鸣

    郑一鸣@yiming2026-10-18

    想问下这种切片方案在字体版本升级的时候怎么处理?全部重下还是只换变化的分片?

  • 吴桐

    吴桐@wutong2026-10-19

    行高和字距那一段说得很实在,中文确实不能照搬西文那套参数。