项目做了一个动画,几个特殊的文字,引入了一个新的字体文件(1.46 MB);又为了几个标题好看,引入了一个更大的字体文件(78.4MB)。
很遗憾,如此粗暴的做法,浏览器拒绝了:
Failed to decode downloaded font: /fonts/%E7%AB%99%E9%85%B7%E5%86%B7%E6%B0%B4%E8%90%A7%E9%9D%92%E5%88%BB%E5%8F%A4%E5%85%B8%E4%BD%93.ttf
index.html:1 OTS parsing error: Web font size more than 30MB
Chrome浏览器拒绝解析30MB以上的字体文件。
于是,开始了寻求字体压缩之路。
直接编辑字体
由于字体文件实在太大,连浏览器都不能解析了,只能对字体文件进行优化。
最初,UI设计把字体文件中的符号、特殊字体以及很大一部分中文进行了删除。
半个小时过后,终于给了我们第二版字体文件。然鹅,中文字删多了,有些字显示不正确。
于是,又过了半个小时。我们收到了第三版。可是,我们发现还是删多了。。
。。。
进行了 几轮的反复的修改测试之后,我们最终拿到了支持所有文字的版本。
但是,字体文件还是>5MB
我们只能得出结论,这只是一个吃力又然并软的办法。
字蛛FontSpider
字蛛是一个中文压缩器。对静态页面友好,但是对于我的React项目就一点都不好。
- 安装
npm install font-spider -g
- 使用方法
在CSS中引用WebFont,并将字体应用于html文件的文本:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<style>
/*声明 WebFont*/
@font-face {
font-family: 'pinghei';
src: url('../font/pinghei.eot');
src:
url('../font/pinghei.eot?#font-spider') format('embedded-opentype'),
url('../font/pinghei.woff') format('woff'),
url('../font/pinghei.ttf') format('truetype'),
url('../font/pinghei.svg') format('svg');
font-weight: normal;
font-style: normal;
}
/*使用选择器指定字体*/
.font-pinghei {
font-family: 'pinghei';
}
</style>
<pre><code class="font-pinghei">
测试文本1哟
0123456789
abcdefghijklmopq
测试文本2哟
</code></pre>
</body>
</html>
- 执行压缩命令
font-spider index.html
因为只保留了选中的文本,压缩后的字体文件会变得很少。1.46 MB大小的文件压缩后只剩大约8k。
可惜在处理78.4MB文件的时候失败了,压缩后的字体只留了部分被选中的文本 (. 这个是为啥呢?)。
我们只得继续。。。
Fontmin
可喜可贺,我们找到了一个非常好的工具。之所以能找到,还要得益于FontSpider。在FontSpider中一探究竟时,我们发现了它其实用的是fontmin。
Fontmin --- 第一个纯 JavaScript 字体子集化方案
于是,学习了一把。发现这真是一个好东西。不仅提供了npm模块,还有跨平台的桌面应用。
本来想自己写一个js来生成字体的,发现它的桌面应用简单好用,就不折腾了,下了Window桌面版。
按提示将字体文件拖入界面
-
输入需要保留的文本
-
点击生成
最终会生成6个文件,包括4个不同格式的字体文件:eot/svt/ttf/woff,一个定义字体的css文件,一个嵌入字体的css文件。
总之一句话,操作简单不报错。
如有需要,强烈推荐。
总结
这几种压缩字体的原理都一样,都是对原有字体文件进行删减,只保留需要的文字。
第一种方法难且效率低;第二种有错误不完善;相对来讲,第三种会更简单一点,如果有需要的话还可以基于它定制自己的自动化脚本。