背景
在我的个人简历网站开发过程中, 使用了自定义的中文字体. 本地开发时效果不错,简洁,美观.但是上线以后发现加载时间特别长. 通过分析,发现中文字体文件高达17MB,对于我这个小水管服务器来说,加载时间超过一分钟. 我调研了各种方案,最后决定使用字体子集化的方案.
本文介绍了一个基于 Vue3 + Vite 的项目中实现字体优化的完整方案。
优化方案
1. 字体子集化
使用 fontmin
工具对字体进行子集化处理,只保留项目中实际使用的字符。
// scripts/font-subset.js
const Fontmin = require('fontmin');
const fs = require('fs');
const path = require('path');
// 配置
const config = {
fontPath: 'src/assets/font/LXGWWenKai-Medium.ttf',
outputPath: 'src/assets/font/subset',
text: '需要保留的字符'
};
// 子集化处理
const fontmin = new Fontmin()
.src(config.fontPath)
.dest(config.outputPath)
.use(Fontmin.glyph({
text: config.text,
hinting: false
}))
.use(Fontmin.ttf2woff2());
2. 自动化构建集成
在 Vite 配置中集成字体子集化流程:
// vite.config.js
export default defineConfig({
plugins: [
{
name: 'font-subset',
buildStart() {
require('./scripts/font-subset');
}
}
]
});
3. 字体加载优化
使用 vite-plugin-font
插件进行字体加载优化:
// vite.config.js
import Font from 'vite-plugin-font';
export default defineConfig({
plugins: [
Font.vite({
scanFiles: ['src/**/*.{vue,ts,tsx,js,jsx}'],
fontFiles: {
'LXGWWenKai': {
path: './src/assets/font/subset/LXGWWenKai-Medium.woff2',
weight: 500,
style: 'normal',
display: 'swap',
preload: true,
format: 'woff2'
}
}
})
]
});
vite-plugin-font
插件的主要功能:
- 自动扫描:自动扫描项目中的字体使用情况
- 预加载配置:支持字体预加载,提高加载性能
- 格式转换:自动处理不同字体格式
- 加载策略:支持配置字体加载策略(如 swap)
- 构建优化:在构建时优化字体文件
4. 字体缓存机制
实现字符缓存机制,避免重复处理:
// 字符缓存文件
const CACHE_FILE = 'font-char-cache.json';
// 读取缓存
function readCharCache() {
try {
return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
} catch {
return { chars: new Set() };
}
}
// 写入缓存
function writeCharCache(chars) {
fs.writeFileSync(CACHE_FILE, JSON.stringify({ chars: Array.from(chars) }));
}
优化效果
-
字体文件大小:
- 原始字体:250KB
- 子集化后:146KB
- 压缩率:约 42%
-
加载性能:
- 使用
font-display: swap
实现无阻塞加载 - 子集化减少网络传输量
- 缓存机制避免重复处理
- 预加载优化首屏加载速度
- 使用
最佳实践
-
字体选择:
- 优先使用系统字体
- 自定义字体作为降级方案
-
格式选择:
- 优先使用 WOFF2 格式
- 提供 TTF 作为降级方案
-
加载策略:
- 使用
font-display: swap
优化加载体验 - 实现字体预加载
- 合理设置字体缓存
- 使用
-
开发流程:
- 自动化字体子集化
- 版本控制字体文件
- 定期更新字符集
注意事项
-
字符集管理:
- 定期检查新增字符
- 及时更新字体子集
- 保留原始字体文件
-
兼容性:
- 提供多种字体格式
- 设置合适的降级方案
- 考虑不同浏览器的支持情况
-
性能监控:
- 监控字体加载时间
- 跟踪字体文件大小
- 评估优化效果
总结
通过字体子集化、自动化构建、加载优化和缓存机制,我们实现了显著的性能提升。这种方案不仅适用于当前项目,也可以作为其他 Web 项目字体优化的参考方案。