前言

博客所需要的第三方字体加载太大了,整整16mb,于是我想办法优化涉及到字体的按需加载和Service Workers。

字体按需加载

字体在普通的css设置中,是会自动加载全部的,但是每次重新刷新网页都会重新下载,于是我用js,在浏览器虚构了一个blob的二进制文件,缓存字体,代码:

 fetch('https://api.yuhenm.com/api/file/source?name=LXGWWenKaiGBScreen.woff', {
    cache: 'force-cache' // 强制缓存
  })
    .then(response => response.blob())
    .then(blob => {
      // 创建字体文件的临时URL
      const fontUrl = URL.createObjectURL(blob);

      // 创建<style>标签
      const style = document.createElement('style');
      // 设置<style>标签的内容
      style.textContent = `
        @font-face {
          font-family: LXGWWenKaiGBScreen;
          font-size: 16px;
          font-style: normal;
          font-display: swap;
          src: url(${fontUrl}) format('woff');
        }
        * {
          font-family: LXGWWenKaiGBScreen;
        }
        body {
          font-family: LXGWWenKaiGBScreen;
        }
      `;
      // 将<style>标签添加到<head>中
      document.head.appendChild(style);

      // 将字体缓存状态标记为已加载
      localStorage.setItem('customFontLoaded', 'true');
    });

但是这还远远不够,虽然说有着onedrive做为流量出口,但是还是太大了,于是我采用了按需加载,用nodejs生成了不同的碎片。

import { fontSplit } from "@konghayao/cn-font-split";

fontSplit({
    FontPath: "./fonts/LXGWWenKaiGBScreen.ttf",
    destFold: "./build",
    css: {
        fontFamily: "LXGWWenKaiGBScreen", // 不建议使用,我们已经有内置的解析模块了
        // fontWeight: 400,
    },
    targetType: "woff2", // ttf woff woff2;注意 eot 文件在浏览器中的支持度非常低,所以不进行支持
    chunkSize: 50 * 1024, // 分割大小
    testHTML: true, // 输出一份 html 报告文件
    reporter: true, // 输出 json 报告
});

这一段代码能将字体进行分割,css文件之所以能按需加载字体内容:

@font-face {
            font-family: "LXGWWenKaiGBScreen";
            src: url("./e9b0555612176c4be508d0952695540e.woff2");
            font-style: normal;
            font-weight: regular;
            font-display: swap;
            unicode-range:U+21,U+22,U+23,U+24,U+25,U+26,U+27,U+28,U+29,U+2A,U+2B,U+2C,U+2D,U+2011,U+2E,U+2F,U+30,U+31,U+32,U+33,U+34,U+35,U+36,U+37,U+38,U+39,U+3A,U+3B,U+3C,U+3D,U+3E,U+3F,U+40,U+41,U+42,U+43,U+44,U+45,U+46,U+47,U+48,U+49,U+4A,U+4B,U+4C,U+4D,U+4E,U+4F,U+50,U+51,U+52,U+53,U+54,U+55,U+56,U+57,U+58,U+59,U+5A,U+5B,U+5D,U+5E,U+5F,U+60,U+61,U+62,U+63,U+64,U+65,U+66,U+67,U+68,U+69,U+6A,U+6B,U+6C,U+6D,U+6E,U+6F,U+70,U+71,U+72,U+73,U+74,U+75,U+76,U+77,U+78,U+79,U+7A,U+7B,U+7C,U+7D,U+7E,U+223C,U+A1,U+A2,U+A3,U+A4,U+A5,U+A6,U+A7,U+A8,U+A9,U+AA,U+AB,U+AC,U+AE,U+AF,U+B0,U+B1,U+B2,U+B3,U+B4,U+2CA,U+B5,U+B6,U+B7,U+2219,U+B8,U+B9,U+BA,U+BB,U+BC,U+BD,U+BE,U+BF,U+C0,U+C1,U+C2,U+C3,U+C6,U+C8,U+CA,U+CB,U+CC,U+CD,U+CE,U+CF,U+D0,U+D2,U+D3,U+D4,U+D5,U+D7,U+D8,U+D9,U+DA,U+DB,U+DD,U+DE,U+DF,U+E6,U+F0,U+F7,U+F8,U+FD,U+FE,U+FF,U+131,U+141,U+142,U+152,U+153,U+160,U+161,U+178,U+17D,U+17E,U+192,U+2C6,U+2C7,U+2D8,U+2D9,U+2DA,U+2DB,U+2DC,U+2DD,U+2014,U+2018,U+2019,U+201A,U+201C,U+201D,U+201E,U+2020,U+2021,U+2022,U+2026,U+2030,U+2039,U+203A,U+2044,U+20AC,U+2122,U+2212,U+FB01,U+FB02,U+3001,U+3002,U+30FB,U+2C9,U+3003,U+3005,U+2015,U+2016,U+3014,U+3015,U+300A,U+300B,U+300C,U+300D,U+300E,U+300F,U+3016,U+3017,U+3010,U+3011,U+2236,U+2227,U+2228,U+2211,U+220F,U+222A,U+2229,U+2208,U+2237,U+221A,U+22A5,U+2225,U+2220,U+2312,U+2299,U+222B,U+222E,U+2261,U+224C,U+2248,U+223D,U+221D,U+2260,U+226E,U+226F,U+2264,U+2265,U+221E,U+2235,U+2234,U+2642,U+2640,U+2032,U+2033,U+2103,U+FF04,U+FFE0,U+FFE1,U+2116,U+2606,U+2605,U+25CB,U+25CF,U+25CE,U+25C7,U+25C6,U+25A1,U+25A0,U+25B3,U+25B2,U+203B,U+2192,U+2190,U+2191,U+2193,U+3013,U+2488,U+2489,U+248A,U+248B,U+248C,U+248D,U+248E,U+248F,U+2490,U+2491,U+2492,U+2493,U+2494,U+2495,U+2496,U+2497,U+2498,U+2499,U+249A,U+249B;
        }

按需加载是依靠 unicode-range 做到的,它能够告诉浏览器字符在哪个文件,从而按需加载。

Service Workers 使用

handsome这个主题是有Service Workers的功能的,我也是看了这一块代码才知道的。

我想要缓存所有资源文件,但是研究了无数次发现依旧不可以,因为有着302定向,每次都不用,这就是onedrive做资源的缺点。

发现Service Workers之所以能够缓存无法是使用了前端的caches接口,所已想着自己魔改。

但是有着hash值的区别和302定向,导致魔改无数次依旧不成功。

还尝试使用indexedDB来进行缓存,不过考虑了一下,还是算了。

最后修改:2023 年 11 月 06 日
如果觉得我的文章对你有用,请随意赞赏