前言
人性的网页浏览体验离不开炫酷的字体。
有时我们只需要显示一两个字、或者只有一行字,那还需要加载几 M 大小的整个字体文件吗?
解决
我们可以使用 fontmin 进行字体抽取。
官方项目:ecomfe / fontmin
安装
yarn add -D fontmin
提取
准备好我们的字体 .ttf
完整文件,建立转换模板如下:
const Fontmin = require("fontmin");
// 自定义
const filePath = "./zhanku.ttf";
const fontName = "zhanku";
const extractText = "我是提取的字体,只有我生效";
const exportPath = "./fonts";
const fontmin = new Fontmin()
.src(filePath)
.use(
Fontmin.glyph({
text: extractText,
hinting: false // keep ttf hint info (fpgm, prep, cvt). default = true
})
)
.use(Fontmin.ttf2eot())
.use(Fontmin.ttf2svg())
.use(
Fontmin.ttf2woff({
deflate: true // deflate woff. default = false
})
)
.use(
Fontmin.css({
fontFamily: fontName,
base64: true
})
)
.dest(exportPath);
fontmin.run();
自定义好我们的 4 个参数:
-
filePath
:字体文件的位置 -
fontName
:font-family 的名称,我们将在之后使用该名称来表示使用该字体 -
extractText
:需要抽取的文字有哪些 -
exportPath
:生成文件导出的文件夹
之后使用 node 运行即可得到字体包!
![](https://i-blog.csdnimg.cn/blog_migrate/d897e2e0ce29d943d3199d309d0bb62e.png)
看一下生成的 .css
文件:
@font-face {
font-family: "zhanku";
src: url("zhanku.eot"); /* IE9 */
src: url("zhanku.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
url(data:application/x-font-ttf;charset=utf-8;base64,......) format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url("zhanku.svg#zhanku") format("svg"); /* iOS 4.1- */
font-style: normal;
font-weight: normal;
}
如此一来我们就得到了 ie 使用的 .eot
,chrome / firefox 等使用的 base64 ,以及 .svg
格式。
使用
我们可以直接加载此 .css
文件即可使用该字体,在 Vue2 中试用如下:
<template>
<div id="app">
这是一段文字<br />
我是提取的字体,只有我生效
</div>
</template>
<style lang="scss">
@import "~@/font/fonts/zhanku.css";
#app {
font-family: zhanku;
}
</style>
使用 ~
作为 @import
的开头表示动态加载,无该标识将找不到该 .css
文件。
效果
![](https://i-blog.csdnimg.cn/blog_migrate/5f124ea807dc93b7770dfd4e443aebbb.png)
已经达到了我们的需求,只有我们提取的字体生效。
看一下文件大小:
![](https://i-blog.csdnimg.cn/blog_migrate/8af94f05950c42b359610cddc086d178.png)
非常符合我们的预期。
使用 CDN
当然这也是能加载本站的字体了,一般情况我们的文件都是放在 cdn 上,需要给所有字体文件添加 cdn 网址前缀,可以更改 .css
生成部分配置如下:
.use(
Fontmin.css({
// 添加 cdn 子路径
fontPath: "https://cdn.domain.com/subpath/",
fontFamily: fontName,
base64: true
})
)
如此一来便得到添加网址前缀的 .css
文件:
@font-face {
font-family: "zhanku";
src: url("https://cdn.domain.com/subpath/zhanku.eot"); /* IE9 */
src: url("https://cdn.domain.com/subpath/zhanku.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
url(data:application/x-font-ttf;charset=utf-8;base64,......) format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url("https://cdn.domain.com/subpath/zhanku.svg#zhanku") format("svg"); /* iOS 4.1- */
font-style: normal;
font-weight: normal;
}
有关转换 css 完整选项可以查看:Generate css config
不使用 base64
当我们的文字稍长时,可能不止几 KB ,此时使用 base64 已经是不明智之选,把 base64 选项置为 false
或注释掉即可:
.use(
Fontmin.css({
fontFamily: fontName
// base64: true
})
)
此时得到的将是各个字体文件的 .css
:
@font-face {
font-family: "zhanku";
src: url("zhanku.eot"); /* IE9 */
src: url("zhanku.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
url("zhanku.woff") format("woff"), /* chrome, firefox */
url("zhanku.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url("zhanku.svg#zhanku") format("svg"); /* iOS 4.1- */
font-style: normal;
font-weight: normal;
}
总结
fontmin 虽然很厉害,但不是万能的,由于 font 文件表之间极其复杂的相互关联,转换得到的子字体将会破坏一部分关联信息(比如会影响字体竖排时的间距)。
但是从最底线来说,文件大小优化我们做到了。