注册
web

20MB 的字体文件太大了,我们把 Icon Font 压成了 10KB

在一次前端性能优化项目中,我们发现仅仅一个 icon font 文件就高达 20MB。这不仅拖慢了首屏加载速度,还极大地浪费了带宽。最终,我们将它压缩到了 10KB,而不影响任何功能表现。


这一过程背后,涉及的不仅是压缩,而是对「构建流程」「字体格式」「加载策略」「字形定制」的全盘重构。本文将逐步拆解这场“减重手术”,帮助你理解 icon font 是如何成为性能黑洞的,又是如何优雅瘦身的。




问题:20MB 的 icon font 是怎么来的?


大字体文件往往是由于以下原因造成的:



  • 过度收录:设计同学导出了一整套 2000 多个图标的 icon font,实际只用了其中几十个。
  • 全量打包:工具如 Icomoon、Fontello、FontForge 默认导出全量字形。
  • 格式冗余:一个字体文件常包含 .ttf, .woff, .woff2, .eot, .svg 多种格式,全打包增加体积。
  • 不做 Subset(子集提取):没有剔除未使用的字形。

最终结果就是:用户下载了 2000 个图标,只为了看到那 20 个常用 icon。




目标:精简为只包含实际使用 icon 的最小字体


如果你只用了 <i class="icon-chevron-down"></i><i class="icon-close"></i><i class="icon-search"></i> 三个图标,那字体文件里应该只包含这三个图形。


核心理念是:用子集字体(Subset Font)只保留被真正使用的字形。




解决方案路线图


✅ 步骤一:收集实际用到的 icon



  • 全站代码扫描,提取 icon class(或 unicode)
  • 工具:自定义脚本、AST 分析、静态资源分析工具

# 示例:查找 iconfont 使用的 class 名称
grep -roh 'icon-[a-zA-Z0-9_-]\+' ./src | sort | uniq > used-icons.txt



✅ 步骤二:精简 icon 到最小集合


工具选择:



  • IcoMoon App:可视化管理图标,导出精简 icon font
  • FontSubset:支持上传字体,自动子集提取
  • pyftsubset(来自 fonttools):命令行方式自动提取子集

例:使用 pyftsubset


pyftsubset original.ttf \
--unicodes=U+E001,U+E002,U+E003 \
--output-file=subset.ttf \
--flavor=woff2 \
--layout-features='*' \
--no-hinting \
--glyph-names

说明:



  • --unicodes 指定只保留的字符
  • --flavor=woff2 输出现代浏览器首选格式
  • --no-hinting 去除微调信息,减小文件体积



✅ 步骤三:只保留必要的字体格式


浏览器现代化后,建议:



  • 只保留 .woff2(现代浏览器支持)
  • 视兼容性决定是否保留 .woff(老一点的 Chrome/Firefox)
  • 移除 .eot / .svg / .ttf 除非需要极限兼容 IE6+

字体大小差异:


格式同内容文件大小
TTF40KB
WOFF28KB
WOFF210KB



✅ 步骤四:字体精简之后如何正确加载?


CSS 示例:


@font-face {
font-family: 'MyIcons';
src: url('icons.woff2') format('woff2');
font-display: swap;
}

重点字段说明



  • font-display: swap:加速首次渲染
  • format('woff2'):浏览器可判断是否支持



✅ 步骤五:如果你用的是组件库的内建 iconfont


Ant Design、Element UI、Bootstrap Icons 等往往内置大量 iconfont。优化策略如下:



  • 替换为 SVG 图标组件(例如 Iconify
  • 只引入需要的图标模块

    • Antd 4.x 以上支持按需引入图标(非字体形式)


  • 使用 Tree-shaking 友好的 SVG icon 方案

    • @iconify/react@icon-park/react





成果验证


经过上述处理:



  • 初始字体大小:20.3MB
  • 实际保留字形数量:12 个
  • 精简后字体(.woff2)大小:10.4KB
  • 首屏加载 TTI 提升:约 800ms
  • Lighthouse 性能评分:+9 分



额外干货:你可能不知道的字体优化技巧


🧠 1. 使用 base64 inline 的 icon font 并非总是好事


虽然可减少 HTTP 请求,但:



  • 无法缓存(每次 HTML 载入)
  • 增加 HTML 大小
  • 不利于 CDN 优化和延迟加载

通常只有在 icon font < 5KB 且需要打包进组件时,才考虑 base64。




🧠 2. 字体子集可以配合 SSR 实现动态优化


在 SSR 应用(如 Next.js)中,可以:



  • 在构建阶段根据页面中实际 icon 自动生成对应的字体子集
  • 动态注入只需要的 icon font,达到更极致的优化效果



🧠 3. 替代方案:彻底摆脱 icon font,用 SVG


SVG 优点:



  • 完全控制颜色/动画
  • 无需额外字体解析
  • 体积更小,支持按需加载
  • 更适合现代组件式开发(React/Vue)

推荐库:



  • Iconify(80+ 图标集统一封装)
  • unplugin-icons(Vite 项目自动加载)
  • Heroicons、Feather、Lucide、Tabler 等



你还在用几兆的 icon font,不妨静下心来,用一下午把它瘦成精悍的 10KB, 别让一堆你永远不会用到的图标,霸占用户的加载时间。


📌 你可以继续看我的系列文章



作者:ErpanOmer
来源:juejin.cn/post/7518572029404397580

0 个评论

要回复文章请先登录注册