You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JavaScript实现字体预下载缓存,优化后续页面字体渲染?

解决方案

核心思路是利用本地存储标记缓存状态+预加载分离渲染逻辑,既保证首次加载不影响FCP,又能让二次刷新直接用缓存字体,完全避免FOUT:

1. 先预加载字体但不关联渲染

在HTML头部添加预加载标签,先把字体下载到浏览器缓存,但不直接在初始CSS里使用它:

<link rel="preload" href="/path/to/your-font.woff2" as="font" type="font/woff2" crossorigin>

注意:crossorigin必须加,哪怕字体和页面同域——浏览器对字体资源的预加载有跨域规则要求。

2. 初始CSS只使用系统 fallback 字体

页面首次加载时,全部文本用系统默认字体渲染,完全不触发自定义字体的加载和切换:

body {
  font-family: 'System UI', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

3. 用 localStorage 控制字体渲染时机

通过JS判断本地存储标记,决定是否加载自定义字体的样式:

// 页面初始化时检查缓存标记
const hasFontCache = localStorage.getItem('fontCached');

if (hasFontCache) {
  // 二次加载(已有缓存):直接注入font-face样式,立即用自定义字体
  const fontStyle = document.createElement('style');
  fontStyle.textContent = `
    @font-face {
      font-family: 'YourCustomFont';
      src: url('/path/to/your-font.woff2') format('woff2');
      font-display: optional; /* 有缓存时立即渲染,无缓存时直接用fallback */
      font-weight: 400;
      font-style: normal;
    }
    body {
      font-family: 'YourCustomFont', 'System UI', -apple-system, sans-serif;
    }
  `;
  document.head.appendChild(fontStyle);

  // 额外:验证字体是否真的加载成功,避免缓存失效的情况
  document.fonts.load('400 16px "YourCustomFont"').catch(() => {
    localStorage.removeItem('fontCached');
  });
} else {
  // 首次加载:监听预加载完成,标记缓存
  const preloadLink = document.querySelector('link[rel="preload"][as="font"]');
  if (preloadLink) {
    preloadLink.addEventListener('load', () => {
      // 字体下载完成,标记已缓存
      localStorage.setItem('fontCached', 'true');
    });
    // 预加载失败时清除错误标记
    preloadLink.addEventListener('error', () => {
      localStorage.removeItem('fontCached');
    });
  }
}

关键细节说明

  • font-display: optional:这个属性是核心——它会告诉浏览器:如果字体在缓存里就立即用;如果没缓存,直接用fallback字体,完全不等待,从根源避免FOUT。
  • 缓存标记的可靠性:只有当预加载的字体确实下载完成后,才会设置localStorage标记,确保二次加载时字体一定在缓存里。
  • 缓存失效处理:通过document.fonts.load()验证字体加载状态,万一用户手动清除了HTTP缓存但localStorage标记还在,会自动移除标记,下次加载重新走预加载流程。

如果你觉得内嵌样式不够整洁,也可以把font-face规则单独写在一个CSS文件里,然后动态创建<link>标签加载:

// 替换上面的内嵌样式逻辑
const fontLink = document.createElement('link');
fontLink.rel = 'stylesheet';
fontLink.href = '/path/to/font-styles.css';
document.head.appendChild(fontLink);

内容的提问来源于stack exchange,提问作者swlv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:17:30