前两种一般是在浏览器构建 CSSOM 时,当遇到**<font style="color:rgba(0, 0, 0, 0.9);">url()</font>**引用时会发起资源请求。第三种则是通过 js 来控制字体的加载流程,所以归根结底就是字体文件太大,导致网络资源下载速度慢,我们只能从优化字体大小的方向入手
确定解决方向
下面汇总下查到的具体几个优化方案,诸如提高网络传输效率,增加缓存之类的就不讲了,能够立竿见影的主要下边这两个方案
简单来说,字体子集化可单独食用,按需加载则必须要将字体前置子集化。才能完美实现按需加载。就我的这个项目而言,动态子集化方案不要太完美,毕竟一张海报本身就没几个字儿!所以我们这次将抛弃 CDN,通过动态的将服务本地中的字体资源子集化来实现字体的压缩效果。
@app.route('/font/<font_name>', methods=['GET'])
def get_font_subset(font_name):
# 获取本地字体文件路径
font_path = os.path.join(FONTS_DIR, f"{font_name}.ttf")
# 获取子集字符
chars = request.args.get('text', '')
# 字体文件格式
format = request.args.get('format', 'woff2').lower()
# 处理字符,去重
unique_chars = ''.join(sorted(set(chars)))
try:
# 配置子集化选项
options = Options()
options.flavor = format if format in {'woff', 'woff2'} else None
options.desubroutinize = True # 增强兼容性
subsetter = Subsetter(options=options)
# 加载字体并生成子集
font = TTFont(font_path)
subsetter.populate(text=unique_chars)
subsetter.subset(font)
# 保存为指定格式
buffer = io.BytesIO()
font.save(buffer)
buffer.seek(0)
# 确定MIME类型
mime_type = {
'woff2': 'font/woff2',
'woff': 'font/woff',
}[format]
# 创建响应并设置
response = Response(buffer.read(), mimetype=mime_type)
# 其他设置...
return response
except Exception as e:
# 子集化失败...