相比于英文的字库来说,中文字库的体积非常之大,小则1M,动辄几十 M 的体积非常常见。所以在前端页面性能优化中,字体加载的优化就显得尤为重要。阅读了相关的知识和文章,在研究了市面上字体加载方案之后,我总结出了目前可行的方案。
1、font-spider
字蛛是一款可以压缩字体文件的小工具,其主要的原理就是,通过html页面获得文字以及对应的字体文件,然后把已经使用文字保留,没有的文字去除,生成一个新的字体文件。
安装
使用:
命令执行完会在原字体处生成一个新的字体文件,而旧的文件会保存在font-spider文件夹下,新生成的就是压缩后的字体文件。至此,工具的使用方法介绍完了。
字蛛工具的优点和缺点都十分的明显。
优点:能够把没有使用的字符丢弃,只保留使用到的字符,这对于字体文件的体积优化是非常大的。
缺点:不够灵活,每次有内容更新都需要跑一遍脚本,而且致命的缺点是只能够识别html文件中的文字,后端返回的文字并不能被识别。所以不能适应于一般的框架项目。当然,如果你愿意再入口文件把你所有用的文字都放进去,然后再压缩,我也没有意见。
2、加载完成前使用降级字体
目前浏览器对于自定义字体不存在时的解决方案有两种:
- 加载完成前隐藏(FOIT, Flash Of Invisible Text)
- 加载完成前使用降级字体(FOUT, Flash Of Unstyled Text)。 很显然,如果选择FOIT的显示方式的话,如果我们的自定义字体没有加载出来的话,那么我们的页面就一直显示的是空白的页面,这对于用户体验来说是致命的。所以,FOUT这个方式才是更合适的解决方案。 提到FOUT,不得不提到一个 @font-face 指令的描述符: font-display
@font-face { font-family: "sans-medium"; src: url(./font/NotoSansSC-Medium.otf); font-display: swap;}
- block:表示文档会block一段时间(阻塞期大概3s)来等待远程字体文件的下载,该时间内字体如没有完成下载,使用备选字体,等远程字体下载完毕后再进行替换。
- swap:表示文档不会block(极短的阻塞期< 1s),直接使用备选字体,远程字体下载完毕后再进行替换。
- fallback:表示文档不会block(极短的阻塞期<1s),直接使用备选字体,并且在交换期(大概是2s)内下载完毕则进行字体替换,否则放弃使用远程字体。
- optional:表示文档不会block(极短的阻塞期< 1s),这么短时间内字体完成加载则使用字体否则放弃使用。
- auto:自动模式,由浏览器决定(chrome下行为跟swap类似)
那么在了解 font-display 之后,那么我们应该不难看出来,对于大部分情况应该把它的值设置为 swap ,这样在加载网络字体期间,使用后备字体进行渲染,加载完成之后在替换为指定的网络字体。
优点:在自定义字体没有加载出来之前,能够正常的显示页面,只不过字体是降级字体。不会因为加载字体文件而导致页面阻塞。
缺点:在自定义文字和默认文字存在较大视觉差异时,会影响用户视觉体验!
3、网络字体
很多公司都会把自己的静态资源放在CDN上,从而增加资源获取速度。字体也不意外,完全可以放在CDN上,增加加载的速度。同时也可以使用第三方字库,如 google font、web font等第三方字库,他们会对字体文件进行自己的优化和处理,能够很大程度的提高加载速度。
优点:加载速度快。
缺点:增加不必要的外链,影响安全性,受制于第三方库
4、字库切分
这个方案,完美的解决了以上3中方案中存在的不足,可以说是目前为止,最为完美的解决方案。
字库切分,顾名思义是把一个字库切分成多个小的字体,减少单个字体文件的大小,从而减少字体阻塞的情况发生。可以在 mdn 关于 unicode-range - CSS: Cascading Style Sheets | MDN (mozilla.org) 的介绍中看到:
浏览器只会在页面使用了该范围中的字符时才会加载对应的字体“分片”。也就是说页面初始化时给浏览器一个目录,在页面要渲染字体时再去根据目录加载所需的字体文件。这不就是字体文件的按需加载嘛
谷歌字体也采用了这一方案,通过机器学习,把一些可能出现在同一个页面的上字符组成一个字体片段,一个中文字体库分割成数百个字体片段,然后通过css的方式进行引入。参考sans字体css。
我们就以谷歌的这个字体为例,只需要把这个css引入到我们的项目之中,然后我们在页面上使用这个字体。
当然,你可以把谷歌的css以及对应的字体切片的文件下载下来,放在项目本地。可以用到一个小工具
google-font-splitter - 一个用于下载谷歌分割字体的命令行工具把我们需要的资源下载下来。
部分css代码:
@font-face {
font-family: "sans-regular";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(s/notosanssc/v26/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.4.woff2)format("woff2");
unicode-range: U+1f1e9-1f1f5, U+1f1f7-1f1ff, U+1f21a, U+1f232, U+1f234-1f237, U+1f250-1f251, U+1f300, U+1f302-1f308, U+1f30a-1f311, U+1f315, U+1f319-1f320, U+1f324, U+1f327, U+1f32a, U+1f32c-1f32d, U+1f330-1f357, U+1f359-1f37e
}
@font-face {
font-family: "sans-regular";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(s/notosanssc/v26/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.5.woff2)format("woff2");
unicode-range: U+fee3, U+fef3, U+ff03-ff04, U+ff07, U+ff0a, U+ff17-ff19, U+ff1c-ff1d, U+ff20-ff3a, U+ff3c, U+ff3e-ff5b, U+ff5d, U+ff61-ff65, U+ff67-ff6a, U+ff6c, U+ff6f-ff78, U+ff7a-ff7d, U+ff80-ff84, U+ff86, U+ff89-ff8e, U+ff92, U+ff97-ff9b, U+ff9d-ff9f, U+ffe0-ffe4, U+ffe6, U+ffe9, U+ffeb, U+ffed, U+fffc, U+1f004, U+1f170-1f171, U+1f192-1f195, U+1f198-1f19a, U+1f1e6-1f1e8
}
<div class="medium">
<span class="bold">HTML、CSS、JavaScript</span>这三个是前端开发中最基本也是最必须的三个技能。前端的开发中,在页面的布局时,
HTML指的是超文本标记语言 (<span class="regular"> Hyper Text Markup Language</span>),这个也是我们网页最常用普通的语言了,
CSS级联样式表(<span class="regular">Cascading Style Sheet</span>)简称“CSS”,通常又称为“风格样式表(<span class="regular">Style Sheet</span>)",它是用来进行网页风格设计的。比如,如果想让链接字未点击时是蓝色的,当鼠标移上去后字变成红色的且有下划线,这就是一种风格。通过设立样式表,可以统一地控制HTML中各标志的显示属性。级联样式表可以使人更能有效地控制网页外观。使用级联样式表,可以扩充精确指定网页元素位置,外观以及创建特殊效果的能力。
JavaScript是一种由Netscape的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如Perl,遗留的速度问题,为客户提供更流畅的浏览效果。当时服务端需要对数据进行验证,由于网络速度相当缓慢,只有28.8kbps,验证步骤浪费的时间太多。于是Netscape的浏览器Navigator加入了Javascript,提供了数据验证的基本功能。
</div>
在我们正常加载这三种字体时的效果:
通过字体切分之后的效果
由此看见,提升的效果还是非常明显的。
优点:
- 比起加载完整字体文件来讲,每个字体片段更小,
- 可以在添加font-display来进行字体降级,从而让用户体验更加友好。
- 按需加载,不需要把所有的字体片段都加载进来。
缺点:对于字体库切片,可能谷歌上的可选字体比较少,如果碰巧你的自定义字体,在谷歌字体上没有找到,那就pass了。或者你有能力进行字体分割,那更好!
5、和产品辨雄雌
优点:全是优点。
缺点:容易被打。
以上就是我整理的字体优化相关的5种方案,总的来说,我个人觉得第五种是最完美的,其次就是第四种。
版权归原作者 卑微小王i 所有, 如有侵权,请联系我们删除。