0

0

实现 React 应用中字体与图片完全预加载后再展示页面的完整方案

碧海醫心

碧海醫心

发布时间:2026-01-16 23:42:09

|

782人浏览过

|

来源于php中文网

原创

实现 React 应用中字体与图片完全预加载后再展示页面的完整方案

通过 react 的 `` 结合资源预加载策略(如 `preload`、`font-face` 控制、图片懒加载拦截),可在首屏渲染前确保字体、关键图片等资源就绪,避免 fout/foit 和破碎图像问题。

在客户端渲染(CSR)的 React 应用中,浏览器默认按 HTML 解析顺序逐步加载 CSS、字体和图片,导致未样式化文本(FOUT)、不可见文本(FOIT)或占位图闪烁等问题。单纯依赖 <Suspense> 并不能自动预加载字体或图片——它仅对 React.lazy() 动态导入的组件支持 Suspense 的异步数据源(如 Relay、React Query v5+) 生效。因此,需组合以下三层策略实现真正“全资源就绪后才显示页面”:

✅ 1. 关键字体:使用 <link rel="preload"> + font-display: optional

在 public/index.html 的 <head> 中预加载核心字体,并禁用不可见文本回退:

<!-- public/index.html -->
<head>
  <link 
    rel="preload" 
    href="/fonts/Inter-Regular.woff2" 
    as="font" 
    type="font/woff2" 
    crossorigin
  >
  <style>
    @font-face {
      font-family: 'Inter';
      src: url('/fonts/Inter-Regular.woff2') format('woff2');
      font-display: optional; /* 关键:无字体时不渲染文本,避免 FOUT */
    }
  </style>
</head>
⚠️ 注意:font-display: optional 要求浏览器在 100ms 内完成加载,否则跳过渲染字体——这正符合“全就绪再显示”的前提。

✅ 2. 关键图片:用 loading="eager" + 自定义 ImageLoader 拦截

避免 <img loading="lazy"> 的默认行为。创建一个可 Suspense 的 <PreloadedImage> 组件:

// components/PreloadedImage.tsx
import { useState, useEffect, Suspense } from 'react';

interface PreloadedImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'src'> {
  src: string;
}

export function PreloadedImage({ src, ...props }: PreloadedImageProps) {
  const [isLoaded, setIsLoaded] = useState(false);
  const [error, setError] = useState(false);

  useEffect(() => {
    const img = new Image();
    img.src = src;
    img.onload = () => setIsLoaded(true);
    img.onerror = () => setError(true);
  }, [src]);

  if (!isLoaded && !error) {
    throw Promise.resolve(); // 触发 Suspense fallback
  }

  return <img src={src} {...props} alt={props.alt || ''} />;
}

路由入口处包裹 <Suspense>:

Glimmer Ai
Glimmer Ai

基于GPT-3和DALL·E2的PPT制作工具

下载
// App.tsx
import { Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div className="loading">Loading assets...</div>}>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/about" element={<AboutPage />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

// 在 HomePage 中使用预加载图片
function HomePage() {
  return (
    <main>
      <h1>Welcome</h1>
      <PreloadedImage 
        src="/hero-banner.jpg" 
        width={1200} 
        height={600} 
        loading="eager" 
      />
      <LogoIcon /> {/* 同理可封装 SVG/图标组件 */}
    </main>
  );
}

✅ 3. 全局资源检查(进阶):用 document.fonts.load() + Promise.all

若需更精确控制(例如等待多个字体族),可在 index.tsx 初始化时校验:

// index.tsx
async function waitForCriticalAssets() {
  const fontPromises = [
    document.fonts.load('16px Inter'),
    document.fonts.load('bold 16px Inter'),
  ];

  const imagePromises = Array.from(
    document.querySelectorAll('img[data-preload]')
  ).map((img) => {
    return new Promise<void>((resolve) => {
      if ((img as HTMLImageElement).complete) resolve();
      else img.addEventListener('load', () => resolve(), { once: true });
    });
  });

  await Promise.all([...fontPromises, ...imagePromises]);
}

// 渲染前等待
waitForCriticalAssets().then(() => {
  const root = ReactDOM.createRoot(document.getElementById('root')!);
  root.render(<App />);
});

? 总结与最佳实践

  • <Suspense> 本身不加载资源,而是协调已触发的异步操作;必须配合手动资源加载逻辑(如 new Image()、document.fonts.load())才能生效;
  • 不要为每个组件加 useEffect 监听加载——统一在根组件或自定义 Hook(如 usePreloadAssets())中集中管理;
  • 生产环境务必启用 HTTP/2 Server Push 或 CDN 缓存优化,使 preload 真正生效;
  • 对非关键资源(如滚动后才出现的图片),仍应保留 loading="lazy" 以提升 LCP。

最终效果:用户看到的是一个空白过渡页(或品牌 Loading 动画),直到所有字体解析完毕、首屏图片解码完成,再一次性渲染完整、样式一致的页面——真正实现“所见即所载”。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

337

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

428

2023.10.12

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

495

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

450

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

3566

2024.03.12

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2911

2024.08.16

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 42.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号