2

前端字体性能优化

 1 year ago
source link: https://scarsu.com/web_font_optimize/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前端字体性能优化

字体文件过大、FIOT(flash of invisible text)字体闪现问题

2022/4/12
1分钟阅读
2

问题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;
});
上次更新: 2022/4/12

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK