优化 Font Awesome 子集以提升性能

Avatar of Adam Rackis
Adam Rackis

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

Font Awesome 是一个非常受欢迎的图标库。不幸的是,它很容易以一种导致性能不佳的方式使用。通过对 Font Awesome 进行子集化,我们可以从它提供的字体文件中删除任何未使用的字形。这将减少通过网络传输的字节数,并提高性能。

让我们在一个 Font Awesome 项目中一起对字体进行子集化,看看它会产生什么影响。在进行的过程中,我假设您正在导入 Font Awesome 提供的 CSS 文件,并使用其网络字体来显示图标。

让我们开始设置

为了演示,我只有一个 HTML 文件,它导入 Font Awesome 的基础 CSS 文件。为了获得合理的图标样本,我列出了我在其中一个副项目中使用的每个图标。

这是在对字体进行子集化之前,我们的 HTML 文件在浏览器中的样子

Screenshot of a webpage with 54 various icons in a single row.

这是 DevTool 的 Network 选项卡,可以看到正在下载的内容。

Screenshot of DevTools Network tab showing a stylesheet without font subsetting that weighs 33.4 kilobytes.

现在让我们看看我们的字体文件渲染所有这些内容需要多少字节。

这是我们的基本情况

我们想看看 Font Awesome 最直接、性能最差的使用方式是什么样的。换句话说,我们想要实现最慢的可能实现,没有任何优化。我正在导入 Font Awesome 提供的 all.min.css 文件。

如上所述,压缩后的文件大小为 33.4KB,这完全没问题。不幸的是,当我们查看 DevTool 的 Font 选项卡时,情况变得更糟了。

Screenshot of DevTools Font tab showing five loaded woff-2 files, ranging in size from 138 kilobytes to 185.
糟糕。仅仅用于字体文件就需要 757KB。用于 54 个图标。

虽然字体文件不像 JavaScript 那样会给您的浏览器带来负担,但它们仍然是浏览器需要下载的字节,仅仅是为了几个小图标。考虑到您的一些用户可能在移动设备上浏览您的网站,远离强大的或快速的互联网连接。

使用 PurifyCSS 的第一次尝试

Font Awesome 的主要样式表包含了数千个图标的定义。但如果我们最多只需要几十个呢?当然我们可以删除不需要的东西吗?

有很多工具可以分析您的代码,并 从样式表中删除未使用的样式。我碰巧正在使用 PurifyCSS。虽然这个库不再积极维护,但思路是一样的,最终,这不是我们想要的解决方案。但让我们看看当我们将 CSS 修剪到仅包含所需内容时会发生什么,我们可以使用以下脚本执行此操作

const purify = require("purify-css");

const content = ["./dist/**/*.js"]; // Vite-built content

purify(content, ["./css/fontawesome/css/all.css"], {
  minify: true,
  output: "./css/fontawesome/css/font-awesome-minimal-build.css"
});

当我们加载新构建的 CSS 文件时,我们通过网络传输的 CSS 字节数量大幅下降,从 33KB 降至 7.1KB!

Screenshot of the DevTools Network tab showing a loaded stylesheet that is 7.1 kilobytes, thanks to removing unused CSS.

但不幸的是,我们的其他 Font Awesome 字体文件没有改变。

Screenshot of the DevTools Font tab showing five loaded font files.

发生了什么?PurifyCSS 履行了它的职责。它确实删除了所有未用图标的 CSS 规则。不幸的是,它无法进入实际的 字体文件 以修剪字形,以及 CSS 规则。

如果有一个像 PurifyCSS 这样的工具可以处理字体文件就好了……

子集化工具来救援!

当然,有一些工具能够从字体文件中删除未使用的内容,它们被称为 子集化工具。一个 子集化工具 分析您的网页,查看您的字体文件,并修剪未使用的字符。有很多用于对字体进行子集化的工具,例如 Zach Leatherman 的 Glyphhanger。事实证明,对 Font Awesome 进行子集化非常简单,因为它自带内置的子集化工具。让我们来看一下。

自动对字体进行子集化

我将要向您展示的自动子集化和手动子集化工具需要付费的 Font Awesome Pro 订阅

Font Awesome 允许您设置它称为 套件 的内容,在 Font Awesome 文档 中将其描述为“一个背包,可以轻松地将您需要的所有图标和精彩内容装入一个小巧轻便的捆绑包中,并轻松地将其挂在项目后面”。因此,与其导入任何和所有 CSS 文件,套件为您提供了一个可以在 HTML 文件的 <head> 中添加的单个脚本标签,从那里,套件仅从字体文件中发送您实际需要的字体字形。

创建套件大约需要一分钟。您会得到一个类似于以下内容的脚本标签

<script src="https://kit.fontawesome.com/xyzabc.js" crossorigin="anonymous"></script>

当脚本加载时,我们现在根本没有 CSS 文件,并且 JavaScript 文件只有 4KB。让我们再次查看 DevTools 的 Fonts 选项卡,看看在我们进行了一些子集化后加载了哪些字体文件。

Screenshot of DevTools Font tab showing 24 loaded font files from subsetting Font Awesome with its auto subsetter.

我们已经从 757KB 降到了 331KB。这减少了 50% 以上。但是我们仍然可以做得更好,特别是如果我们只渲染 54 个图标。这就是 Font Awesome 的手动字体子集化工具发挥作用的地方。

手动对字体进行子集化

如果 Font Awesome 为我们提供了一个工具,让我们真正挑选我们想要的精确图标,然后为提供自定义构建,那不是很好吗?好吧,他们做到了。出于某种原因,他们没有大声宣传这一点,但他们实际上确实有一个桌面应用程序,专门用于手动对字体进行子集化。该应用程序可以 从他们的网站下载 - 但与自动子集化工具一样,此应用程序需要付费的 Font Awesome 订阅才能实际使用。

Screenshot of the Font Awesome desktop app. Icons are displayed as tiles in a grid layout.

搜索图标,选择字体系列,添加您想要的内容,然后单击蓝色的大构建按钮。这确实是生成 Font Awesome 图标自定义子集所需的一切。

单击按钮后,Font Awesome 会询问它应该将自定义构建保存到哪里,然后它会转储一个包含您需要的所有内容的 ZIP 文件。实际上,您将获得的结构与正常的 Font Awesome 下载完全相同,这使得事情变得特别简单。当然,它允许您将自定义构建保存为项目文件,以便以后可以重新打开它,根据需要添加或删除图标。

我们将打开 DevTools 以查看我们正在加载的图标的最终大小,但首先,让我们看看实际的字体文件本身。自定义构建会创建许多不同类型,具体取决于您的浏览器使用什么。让我们关注 .woff2 文件,这是 Chrome 加载的文件。之前存在的相同 light、regular、duotone、solid 和 brand 文件仍然存在,只是这次没有哪个文件大于 5KB……而且这是在它们被压缩之前!

Screenshot of the various font files in a project directory.

CSS 文件怎么样?它缩减到只有 8KB。使用 gzip 后,它只有 2KB!

这是 DevTools 中的最终汇总

Screenshot of the DevTools Network tab showing five loaded fonts with Base64 encoding from font subsetting.

在结束之前,快速查看一下这些字体文件名。fa-light-300.woff2 字体文件仍然存在,但其他文件看起来有所不同。这是因为 我正在使用 Vite,它决定自动将字体文件内联到 CSS 中,因为它们非常小。

Screenshot of the inlined Base64 encoding in th at-font-face declaration of a CSS file.

这就是为什么我们的 CSS 文件在 DevTools Network 选项卡中看起来比我们之前在磁盘上看到的 2KB 大一点。权衡是,上面大多数字体“文件”根本不是文件,而是嵌入到此 CSS 文件中的 Base64 编码字符串,从而节省了额外的网络请求。

Screenshot of the DevTools Network tab showing a single CSS file that weighs 20.7 kilobytes.

话虽如此,Vite 正在内联浏览器永远不会使用的许多不同的字体格式。但总的来说,字节数非常少,特别是与我们之前看到的相比。

在离开之前,如果您想知道那个桌面字体子集化 GUI 工具是否有一个可以与 CI/CD 集成以在构建时生成这些文件的 CLI,答案是……还没有。我给 Font Awesome 的人员发了邮件,他们说正在计划一些内容。如果并且当它发布时,这将允许用户简化他们的构建流程。


正如你所见,使用 Font Awesome 之类的图标库非常酷。但默认的使用方式可能并不总是最适合你的项目。为了获得尽可能小的文件大小,我们可以对字体进行子集化处理,剔除不需要的部分,只提供我们需要的内容。尤其是在加载字体方面,我们希望获得这种性能提升,因为字体传统上一直难以处理