web处理字体(font-family)分析

811 阅读4分钟

问题起因

年前简简单单赶工一个大屏,在代码review的时候看到如下一幕

@font-face {
    font-family: 'SourceHanSansCN-Regular';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Regular.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Bold';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Bold.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-ExtraLight';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-ExtraLight.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Light';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Light.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Normal';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Normal.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Medium';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Medium.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Heavy';
    src: url('~@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN-Heavy.otf');
    font-weight: normal;
    font-style: normal;
}

import "@/assets/styles/fonts/SourceHanSansCN/SourceHanSansCN.css";

然后顺带看了一眼这些字体文件。。

image.png

可以,60多M,这不得起飞。但是还原度卡的好严格,又不能不用这些字体。于是想研究一下在保证字体正常显示的前提下,是否有优化的空间

提出问题

首先,如果按照上面的方式引入文字,会导致什么问题呢?先写个测试用例

@charset "UTF-8";
@font-face {
    font-family: 'SourceHanSansCN-Regular';
    src: url('../font/SourceHanSansCN-Regular.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Bold';
    src: url('../font/SourceHanSansCN-Bold.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-ExtraLight';
    src: url('../font/SourceHanSansCN-ExtraLight.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Light';
    src: url('../font/SourceHanSansCN-Light.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Normal';
    src: url('../font/SourceHanSansCN-Normal.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Medium';
    src: url('../font/SourceHanSansCN-Medium.otf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'SourceHanSansCN-Heavy';
    src: url('../font/SourceHanSansCN-Heavy.otf');
    font-weight: normal;
    font-style: normal;
}

.medium {
    font-family: PingFangSC-Medium
}
.regular {
    font-family: SourceHanSansCN-Regular
}
.bold {
    font-family: SourceHanSansCN-Bold
}
.extra-light {
    font-family: SourceHanSansCN-ExtraLight
}
.heavy {
    font-family: SourceHanSansCN-Heavy
}
.light {
    font-family: SourceHanSansCN-Light
}
.medium {
    font-family: SourceHanSansCN-Medium
}
.normal {
    font-family: SourceHanSansCN-Normal
}
    <div class="regular">测试 test 1234567890</div>
    <div class="bold">测试 test 1234567890</div>
    <div class="extra-light">测试 test 1234567890</div>
    <div class="heavy">测试 test 1234567890</div>
    <div class="light">测试 test 1234567890</div>
    <div class="medium">测试 test 1234567890</div>
    <div class="normal">测试 test 1234567890</div>

看看效果 火焰图如下

image.png

所以大量的字体引入有如下弊端

  1. 资源下载量大,阻碍资源加载
  2. 加载过程中随着文字资源加载存在大量css样式偏移,影响用户体验
  3. 延长打包速度,增加项目包体积

解决方案:

  1. 首先这类体积较大的静态文件首选的处理方案当然是加缓存

缓存前后对比

乍一看解决了大部分的问题,但是在初次加载或者更新后hash出现变化的情况又该如何处理呢?

  1. 尝试使用font-display

首先简单介绍一下font-display

属性值效果
block短暂阻塞周期,无限交换周期(字体未加载时用透明的占位字体展示,加载完成后替换)
swap非常短阻塞周期,无限交换周期 (字体未加载时用默认字体展示,加载完成后替换)
fallback非常小的阻塞周期和短暂的交换周期
optional非常小的阻塞周期,并且没有交换周期。(基本上只能展示本地字体,不等待加载线上字体)

这样看起来使用font-display貌似只能优化体验,那些字体文件还是需要加载的,用处不大

  1. 字体体积压缩
    查阅资料发现 woff,woff2的字体是otf,ttf的压缩版本。可以将字体压缩成woff以减小体积。但是我压缩了几次都失败了。 还有说法是使用font-spider提取所有使用这种字体的问题进行极限压缩。但是我们这里用的也是动态数据,按道理无法实现。

  2. 字体引入优化
    (过年时公司服务关停了,之后再在项目里做调整,至少不能让这么大量的字体在初始化时一股脑引入进来)

  3. 字体本地化??
    这里提供了一些关于google/font的优化方案,大概浏览了一遍,感觉大致的方式也在上面提过了。在面对中文且多fontWeight字体的情况下没啥帮助。但是其中提到了一点

image.png 不知能否把这些字体在播放大屏的电脑本地化呢?如果可以应该就没有网络加载这么多麻烦事了。这个也需要年后在看了