前端字体性能优化
字体文件过大、FIOT(flash of invisible text)字体闪现问题
问题1:字体文件过大,解决方案:Fontmin - 字体子集化
介绍
Fontmin是一个纯JS字体子集化方案,用于压缩字体文件。
依赖node环境。
其原理是扫描项目中的文字,将用到的字从字体文件中单独拿出来组成一个子集字体文件。
可以达到大幅度减小字体文件尺寸的效果。
相关资源
安装
npm install --save-dev fontmin
使用
const fs = require("fs");
const Fontmin = require("fontmin");
//扫描文件目录
const scanFolder = (dir, done) => {
let results = [];
fs.readdir(dir, (err, list) => {
if (err) {
return done(err);
}
let i = 0;
(function iter() {
let file = list[i++];
if (!file) {
return done(null, results);
}
file = dir + "/" + file;
fs.stat(file, (err, stat) => {
if (stat && stat.isDirectory()) {
scanFolder(file, (err, res) => {
results = results.concat(res);
iter();
});
} else {
results.push(file);
iter();
}
});
})();
});
};
//Fontmin根据文字内容生成压缩后的字体子集
const generateFinalHTML = (finalString) => {
const fontmin = new Fontmin()
.src('static/fonts/*.ttf') // 需要压缩的所有字体文件
.dest('static/fonts/') // 压缩后文件存储路径
.use(
Fontmin.glyph({
text: finalString,
hinting: false,
})
)
.use(
Fontmin.ttf2woff({
deflate: true,
})
);
fontmin.run((err) => {
if (err) {
throw err;
}
});
};
//获取目录下所有文件的文字内容
scanFolder("dist", (n, results) => {
let set = new Set();
results.forEach((file) => {
const result = fs.readFileSync(file, "utf8");
const currentSet = new Set(result);
set = new Set([...set, ...currentSet]);
});
generateFinalHTML(Array.from(set).join(""));
});
问题2:FOIT(Flash of Invisible Text )字体闪现问题
问题描述
浏览器在加载字体时,默认不展示文本内容,在现代浏览器中,FOIT会导致这种现象出现至多3秒。
如果有文字混搭(有的字体需要加载,有的字体不需要)那么用户可能就会发现“网页只显示部分字体”的情况,用户体验很差。
解决步骤1:font-display:swap
:未加载到字体时,优先显示替代字体,而不是空白(MDN文档)。
font-display
属性决定了一个@font-face在不同的下载时间和可用时间下是如何展示的。
@ font-face {
font-family: ExampleFont;
src: url(/path/to/fonts/examplefont.woff)format('woff'),
url(/path/to/fonts/examplefont.eot)format('eot');
font-weight: 400;
font-style: normal;
font-display: fallback;
}
解决步骤2:preload
:预加载字体文件,提前加载字体。
<link rel="preload" type="font/woff" href="/fonturl" as="font" crossorigin="true">
解决步骤3:document.fonts.ready
接口:浏览器处理完成字体加载后的回调(加载成功或者失败都会触发回调)
document.fonts.ready.then(() => {
// 字体加载完成后的逻辑
this.fontLoaded = true;
});
上次更新: