Introduction

The blog requires loading third-party fonts, which can be quite large, a whopping 16MB. As a result, I sought to optimize the on-demand loading of fonts and leverage Service Workers.

On-Demand Font Loading

In a typical CSS setup, fonts are automatically loaded, but every time the webpage is refreshed, they are downloaded again. To address this, I used JavaScript to create a binary blob file in the browser, caching the font. Here's the code:

fetch('https://api.yuhenm.com/api/file/source?name=LXGWWenKaiGBScreen.woff', {
    cache: 'force-cache' // Force cache
})
.then(response => response.blob())
.then(blob => {
    // Create a temporary URL for the font file
    const fontUrl = URL.createObjectURL(blob);

    // Create a <style> tag
    const style = document.createElement('style');
    // Set the <style> tag's content
    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;
        }
    `;
    // Add the <style> tag to <head>
    document.head.appendChild(style);

    // Mark the font caching status as loaded
    localStorage.setItem('customFontLoaded', 'true');
});

However, this was not sufficient. Although I had OneDrive as a traffic outlet, the font size was still too large. To address this, I implemented on-demand loading by splitting the font into different fragments using Node.js.

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

fontSplit({
    FontPath: "./fonts/LXGWWenKaiGBScreen.ttf",
    destFold: "./build",
    css: {
        fontFamily: "LXGWWenKaiGBScreen", // Not recommended; we already have a built-in parsing module
    },
    targetType: "woff2", // ttf woff woff2; note that browser support for eot files is very low, so we do not support it
    chunkSize: 50 * 1024, // Split size
    testHTML: true, // Output an HTML report file
    reporter: true, // Output a JSON report
});

The code above splits the font, allowing CSS to load the font content on demand:

@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

On-demand loading is achieved through the use of unicode-range, which tells the browser which characters are in which files, allowing for on-demand loading.

Service Workers Usage

The "handsome" theme of this blog has Service Workers functionality, which I discovered by examining this section of the code.

I wanted to cache all resource files, but after numerous investigations, it still wasn't possible due to 302 redirects, as each request was not reused. This is a drawback of OneDrive as a resource source.

I noticed that Service Workers can cache successfully due to the use of the front-end caches interface. So, I considered modifying it myself.

However, due to the hash value differences and 302 redirects, my modifications were unsuccessful after numerous attempts.

I also attempted to use indexedDB for caching but ultimately decided against it.

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