项目优化之--字体优化

330 阅读4分钟

字体介绍

可参考这篇文章 介绍

字体文件格式:

TTF 包含一个单独的字体样式文件(普通、斜体、粗体)等

OTF 它基于支持扩展字符集(连字、替代样式、字形等)的 TrueType 格式

WOFF 这个字体格式使用zlib压缩,文件一般比ttf小40%左右

WOFF2 使用Brotli方法压缩,在woff基础上进一步优化了体积

背景介绍

当我们在页面中引入自定义字体的时候,使用 @font-face 设置, 如果自定义字体包特别大的话,会导致页面在渲染的时候,出现字体加载空白问题,也就是所谓的 FOIT (Flash Of Invisible Text) 会发现页面结构和图片出来了,但是文字区域是空白的

这是因为当使用font-face下载字体的时候,浏览器需要等文件下载完成后,并且还要去解析页面内容,看文档中有没有节点使用了@font-face 的字体,才去决定是否需要下载字体。当浏览器开始下载字体,使用了该字体的所有文本会被隐藏,导致页面出现空白

解决方案

为了解决 FOLT 这种现象,我们可以使用css的font-display可以解决此问题

css的font-display有五个值,分别是

auto: 使用浏览器默认的行为;

block:浏览器首先使用隐形文字替代页面上的文字,并等待字体加载完成再显示;

swap:如果设定的字体还未可用,浏览器将首先使用备用字体显示,当设定的字体加载完成后替换备用字体;

fallback:与 swap 属性值行为上大致相同,但浏览器会给设定的字体设定加载的时间限制,一旦加载所需的时长大于这个限制,设定的字体将不会替换备用字体进行显示。 Webkit 和 Firefox 中设定此时间为 3s;

optional:使用此属性值时,如果设定的字体没有在限制时间内加载完成,当前页面将会一直使用备用字体,并且设定字体继续在后台进行加载,用于下一次浏览时可以直接使用设定的字体。

除了 css 的 font-display 外,还提供了 FontFaceSet 接口加载字体,还可以使用js 监听加载事件,当字体加载完成后替换class,效果如同 font-display: swap 效果。这里不再过多介绍

使用上面办法优化后,会发现还会有另外一个问题,字体加载完成之后,页面闪了一下,这是因为备用字体和自定义字体外形差距太大导致的,这种现象又称为 FOUT (Flash Of Unstyled Text)

我们可以通过缩小字体体积,以及优化加载速度来进行优化

字体加载优化方案

预加载

通过预加载 web 字体提高加载速度

<link rel="preload" href="https://font.com/myFont.woff2" as="font" type="font/woff2" crossorigin>

as="font" type="font/woff2"属性会告诉浏览器将此资源作为字体下载,并帮助确定资源队列的优先级。

crossorigin 属性说明是否应使用 CORS 请求获取资源,因为字体可能来自不同的域。如果不设置此属性,浏览器将忽略预加载的字体。

利用 fontfaceobserver 判断字体加载完成

npm i fontfaceobserver
// 可参考链接: https://juejin.cn/post/6844903431832862728

// css 中 @font-face 已定义好
import FontFaceObserver from 'fontfaceobserver'

loadfont(){
    console.time("字体加载用时")
    var ooo = new FontFaceObserver('Regular')
    ooo.load().then(() =>{
        document.getElementById('index').style.fontFamily = 'Regular'
        console.timeEnd("字体加载用时")
    })
},

设置 font-display: fallback,同时 preload web font,尽可能在 100ms 内加载完网络字体。

// 优先查找本地系统中是否存在 Alegreya 字体,没有再去加载字体文件。
@font-face {
  src: local("Alegreya"),
    url("./fonts/Alegreya/static/Alegreya-Bold.ttf") format("truetype");
}

字体体积优化方案

1. ttf 转 woff2

使用 node 工具库,将 ttf 格式字体转换为 woff2 格式

npm install ttf2woff2 -g
cat PingFangBold.ttf  | ttf2woff2 > pingfangblod.woff2

2. 使用 Fontmin

具体使用参考: ecomfe.github.io/fontmin/

3. 使用 font-spider

为了压缩字体体积,将页面字体单独提出压缩出一份新的字体文件。

例如: 0123456789课程前瞻 是页面中用到的 PingFangRegular.ttf 的字体

<!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>
<style>
  @font-face {
    font-family: 'pingfangregular';
    src: url('./PingFangRegular.ttf');
    font-weight: normal;
    font-style: normal;
  }
  div {
      font-family: 'pingfangregular';
  }
  </style>
<body>
  <div>
    0123456789课程前瞻
  </div>
</body>
</html>

利用 font-spider 将这几个字体提取出来组成一份新的字体

npm install font-spider  
font-spider index.html 

4. 使用 unicode-range