广州总部电话:020-85564311
广州总部电话:020-85564311
20年
互联网应用服务商
请输入搜索关键词
知识库 知识库

优网知识库

探索行业前沿,共享知识宝库

盘点字体性能优化方案

发布日期:2025-07-15 08:53:30 浏览次数: 813 来源:前端早读课
推荐语
优化网页字体加载性能的实用方案,提升用户体验与首屏速度。

核心内容:
1. WOFF2 字体格式的优势与兼容性分析
2. CSS unicode-range 子集化技术详解
3. 增量字体传输与 Google Fonts 按需加载实践
小优 网站建设顾问
专业来源于二十年的积累,用心让我们做到更好!

前言

通过使用 WOFF2、CSS unicode-range 子集化、增量字体传输(IFT)以及 Google Fonts 按需加载等技术手段,可以显著优化网页字体加载性能,降低字体体积,加快首屏渲染速度。

正文从这开始~~

一,WOFF2 字体文件格式优化

W3C 标准: https://www.w3.org/TR/WOFF2/

方案简介

WOFF2 (Web Open Font Format 2) 字体文件格式已经是 W3C 标准,无需考虑兼容性问题.

WOFF2 通过优化编码格式和更先进的压缩算法使字体文件压缩率提升 (WOFF2 相比 TTF/OTF 压缩率提升 40%-60%,相比 WOFF1 压缩率提升 30%), 同时具备更快的客户端解析速度.

下面是主流字体文件格式对比

以下是常见 Web 字体格式的对比表格,综合了技术特性、兼容性及适用场景:

格式
全称
浏览器兼容性
压缩率
核心优势
主要缺点
TTF
TrueType Font
全平台支持(Windows、macOS、Linux、移动端)
通用性强,支持 Unicode 和高级排版(连字、字距调整)
文件体积大,移动端加载慢
OTF
OpenType Font
全平台支持
支持 PostScript 轮廓,适合专业排版(如印刷设计)
文件体积大,移动端加载慢
WOFF
Web Open Font Format
主流浏览器(Chrome、Firefox、Edge、Safari)
高(比 TTF/OTF 小 40%)
专为 Web 设计,支持压缩和元数据(如许可证信息)
压缩率低于 WOFF2, 不支持旧版浏览器
WOFF2
Web Open Font Format 2.0
现代浏览器(Chrome 40+、Firefox 36+、Edge、Safari 12.1+)
极高(比 WOFF 小 30%)
Brotli 压缩算法,体积最小;支持高级特性(如可变字体)
不支持旧版浏览器
场景分析

在本地能控制字体文件格式的情况下,都应该使用 WOFF2; 在使用字体平台的情况下,基本都支持 WOFF2;

二,CSS unicode-range 字体子集化

unicode-range 已经是 W3C 的 CSS 标准,无需考虑兼容性问题。不需要服务端支持;

W3C 标准:https://www.w3.org/TR/css-fonts-4/#unicode-range-desc

MDN 文档: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range

方案简介

在 CSS 中,@font-face 规定只有在 unicode-range 属性范围内的文字使用该字体;

DOM 文字渲染过程命中了 unicode-range 范围,才会下载该字体子集;

因此可以将一个字体拆分成多个字体子集,根据每个字体子集的 unicode-range 设置多个 @font-face

应用实例

鸿蒙开发者官网 的鸿蒙字体使用了 unicode-range 字体子集化方案,将同一字体拆分成 96 个子集,不同字重也拆分成不同子集,完整字体 WOFF2 体积为 8.1M, 首屏字体子集请求 44 个共计下载 1.1M 字体子集;

LESS 代码如下 (也可以自行调试鸿蒙开发者官网)

@fontUrl:'@/assets/fonts/HarmonyOS/HarmonyOS_Sans';

@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Light.1.woff2")format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  unicode-range: U+ff03,U+ff04,U+ff07,U+ff0a,U+ff17-ff19,U+ff1c,U+ff1d,U+ff20-ff3a,U+ff3c,U+ff3e-ff5b,U+ff5d,U+ffe0-ffe4;
}
@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Regular.1.woff2")format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+ff03,U+ff04,U+ff07,U+ff0a,U+ff17-ff19,U+ff1c,U+ff1d,U+ff20-ff3a,U+ff3c,U+ff3e-ff5b,U+ff5d,U+ffe0-ffe4;
}
@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Light.2.woff2")format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  unicode-range: U+f92c,U+f979,U+fa11,U+fe30,U+fe31,U+fe33-fe44,U+fe49-fe52,U+fe54-fe57,U+fe59-fe66,U+fe68-fe6b;
}
@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Regular.2.woff2")format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+f92c,U+f979,U+fa11,U+fe30,U+fe31,U+fe33-fe44,U+fe49-fe52,U+fe54-fe57,U+fe59-fe66,U+fe68-fe6b;
}
 ...略...
@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Light.96.woff2")format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  unicode-range:
 U+df-e5,U+e7-ea,U+ec,U+ed,U+f1-f4,U+f6,U+f9,U+fa,U+fc,U+101,U+103,U+113,U+12b,U+148,U+14d,U+16b,U+1ce,U+1d0,U+300,U+301,U+1ebf,U+1ec7,U+3042,U+3044,U+3046,U+3048,U+304a-3055,U+3057,U+3059-305b,U+305d,U+305f-3061,U+3063-306b,U+306d-3073,U+3075,U+3076,U+3078,U+3079,U+307b,U+307e,U+307f,U+3081-308d,U+308f,U+3092,U+3093,U+30a1-30a4,U+30a6-30bb,U+30bd,U+30bf-30c1,U+30c3,U+30c4,U+30c6-30cb,U+30cd-30d7,U+30d9-30e1,U+30e3-30e7,U+30e9-30ed,U+30ef,U+30f3;
}
@font-face{
  font-family: HarmonyOSHans-Regular;
  src:url("@{fontUrl}/HarmonyOS_Sans_SC_Regular.96.woff2")format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range:
 U+df-e5,U+e7-ea,U+ec,U+ed,U+f1-f4,U+f6,U+f9,U+fa,U+fc,U+101,U+103,U+113,U+12b,U+148,U+14d,U+16b,U+1ce,U+1d0,U+300,U+301,U+1ebf,U+1ec7,U+3042,U+3044,U+3046,U+3048,U+304a-3055,U+3057,U+3059-305b,U+305d,U+305f-3061,U+3063-306b,U+306d-3073,U+3075,U+3076,U+3078,U+3079,U+307b,U+307e,U+307f,U+3081-308d,U+308f,U+3092,U+3093,U+30a1-30a4,U+30a6-30bb,U+30bd,U+30bf-30c1,U+30c3,U+30c4,U+30c6-30cb,U+30cd-30d7,U+30d9-30e1,U+30e3-30e7,U+30e9-30ed,U+30ef,U+30f3;
}
场景分析
  • 通过良好的拆分字体子集,可以减少首屏加载字体文件的体积;大部分情况下,unicode-range 字体子集化方案都可以减少 40% 到 70% 的字体文件体积;
  • 在多语言和中文场景,对性能提升有显著效果;
  • 同时不应该忽略的是字体子集化会增加网络请求的数量,应该避免造成负向优化;

三,增量字体传输方案 Incremental Font Transfer (IFT)

W3C 标准 (草稿阶段): Incremental Font Transfer

方案简介

IFT 处于 W3C 标准的草案阶段,将字体文件类比成 video, 将 unicode 类比成 video 的时间轴,让浏览器自动下载所需要的字体子集;

从高层次来看,增量字体的使用方式如下:

  • 客户端下载初始字体文件,其中包含来自字体完整版本的一些初始数据子集以及描述可用于扩展字体的补丁集的嵌入数据。
  • 客户端会根据待渲染的内容选择、下载并应用补丁来扩展字体,使其涵盖更多字符、布局特性和 / 或变体空间。每次有新内容时,都会重复此步骤。

下面我用比较形象的两个图展示:

Video 播放根据时间切片进行增量传输,最开始只需要下载时间轴和 video 的元数据即可,包含时间轴和 video 切片的对应关系,播放过程会自动下载 video 切片;

字体根据 unicode 进行增量传输,最开始只需要下载 unicode 和字体子集的对应关系即可,DOM 渲染过程会自动请求增量字体

W3C 标准规定了增量字体的编码方式,以便客户端代理或者服务端代理可以返回增量子集;

客户端将自动识别增量字体并请求增量子集,前端开发人员未来就不用操心字体体积优化了;

目前该提案还在草案阶段,完全自动的字体优化还未能实现;因此后面的方案都是自行实现的增量字体传输方案;

四,Google Fonts 字体按需加载

Google Fonts, Typekit 等字体平台都提供 Web Font 服务,目前发现 Google Fonts 不仅提供字体全量下载,WOFF2 字体格式,字体子集下载等服务,还提供字体按需加载能力;

Google Fonts API:

向 API 传入 text 参数,将只下载参数 text 内包含的字体子集

方案简介
  • 1、前端动态进行网页内容识别,输出网页需要渲染的文字: textConten
  • 2、根据 textContent 生成字体子集的 @font-face 并插入文档流: @font-face 的 src 的 url 指向 https://google-font-api?text=textConten
  • 3、浏览器 DOM 文档渲染命中 @font-face 规则,向 google fonts 服务端请求下载字体子
  • 4、Google Fonts 服务端返回仅包含 textContent 的字体子集,浏览器重新渲染文字
    按需加载字体子集的思路,不一定要生成 @font-face CSS, 还可以使用 FontFace Api 直接下载字体子集,例如:
 const text = textContent;
 // 构建字体对象
 const font = new FontFace(
     fontName,
     `url(http://127.0.0.1:5000/font/${fontName}?text=${text}&format=woff2)`
);
 // 加载字体
 font.load();
 // 添加到文档字体集中
 document.fonts.add(font);
场景分析
  • 在运营场景,首屏存在多种字体,并且只有特定元素如 banner, logo, slogan 等才使用的字体,按需加载可以带来大幅度的性能提升和用户体验提升;
  • 在服务端渲染页面使用字体按需加载将获得极致字体性能
  • 在需要处理用户中文输入的情况下,体验不佳 - 会发起大量单个文字的字体子集请求,并且页面文字渲染可能发生跳变 (用户输入场景,unicode-range 方案浏览器会自动下载字体子集;按需加载方案需要我们主动监听文档流变化)
  • 不一定依赖服务端,在活动页,运营页等场景,可以!!提前!!!! 按需!!生成字体子集即可;
技术细节
  • 识别网页渲染内容的算法: nathanford/google-fonts-dynamic-subsetter
  • 动态监听网页内容变化的算法需要自行判断是否需要动态监听: MDN - MutationObserver
  • 服务端按需生成字体子集的工具

工具附录

1、fontmin:https://ecomfe.github.io/fontmin/#banner

baidu EFE:团队出品的字体子集化工具,基于 nodejs 编写,有客户端,cli, 还有 nodejs api 可以基于它做字体按需加载服务端

2、fonttools:https://github.com/fonttools/fonttools

一个使用 python 操作字体文件的库,可以将字体文件在各种编码之间快速转换,也可以拆分字体子集

3、glyphhanger:https://www.zachleat.com/web/glyphhanger/

使用 puppeteer 爬取网页所有的文字,输出 unicode-range 便于拆分字体子集;- 可以根据 unicode-range 将输入的字体文件拆分出字体子集 (这部分功能封装的是 fonttools)

4、font-spider:https://github.com/aui/font-spider

功能同 glyphhanger, 同样使用 puppeteer 爬取网页内容生成 unicode-range, 并且可以将字体拆分出字体子集,不同的是 font-spider 有 webpack/grunt/gulp 插件,可以在本地构建阶段自动化地为 SPA 打包处最小量的字体子集,font-spider 内部封装的是 fontmin

glyphhanger 使用示例:爬取网页,按需输出字体子集

关于本文
作者:@张庭岑
原文:https://mp.weixin.qq.com/s/f-HCjWiUQ17wXzlLWHtahg


优网科技,优秀企业首选的互联网供应服务商

优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!

优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、微信小程序定制开发、移动端应用(手机站APP开发)、微信定制开发(微信官网、微信商城、企业微信)等一系列互联网应用服务。


我要投稿

姓名

文章链接

提交即表示你已阅读并同意《个人信息保护声明》

专属顾问 专属顾问
扫码咨询您的优网专属顾问!
专属顾问
马上咨询
扫一扫马上咨询
扫一扫马上咨询

扫一扫马上咨询