React + Vite项目优化:public目录大图片加载延迟解决方案
问题描述
在Vercel上部署React + Vite Web应用后,初始页面加载时一张约2.4MB的图片需要12秒才能显示,用户体验差;同时图片后方的SVG也存在加载延迟问题,需要优化加载流程,重点处理public目录中的图片。
现有代码
图片组件代码
export default function MyImg({ containerStyles }: ImgProps) { return ( <div className={`${containerStyles}`}> <img src="/check.png" alt="Picture" className="object-contain" /> </div> ) } interface ImgProps { containerStyles: string; }
布局代码
<div className="hidden lg:flex relative"> <div className="bg-hero w-[500px] h-[500px] bg-no-repeat absolute -top-16 -right-8 overflow-hidden"> <MyImg containerStyles="w[-410px] h-[362px] bg-no-repeat relative -right-30" /> </div> </div>
CSS代码
.bg-hero { background-image: url(/pic-lob.svg); }
优化方案
1. 图片压缩与格式转换
2.4MB的PNG体积过大,优先转换为WebP或AVIF格式,这类格式压缩率远高于PNG,能大幅减小文件体积:
- 用压缩工具(如Squoosh)将
check.png转换为check.webp和check.avif,上传到public目录 - 修改图片组件,用
<picture>标签实现多格式兼容,让浏览器自动选择最优格式:
export default function MyImg({ containerStyles }: ImgProps) { return ( <div className={`${containerStyles}`}> <picture> <source srcSet="/check.avif" type="image/avif" /> <source srcSet="/check.webp" type="image/webp" /> <img src="/check.png" alt="Picture" className="object-contain" /> </picture> </div> ) } interface ImgProps { containerStyles: string; }
2. 启用懒加载
给非首屏图片添加loading="lazy"属性,让浏览器在图片进入视口时再加载,减少初始加载压力:
// 在img标签中添加属性 <img src="/check.png" alt="Picture" className="object-contain" loading="lazy" />
如果该图片是首屏关键资源,不要加懒加载,反而可以设置fetchpriority="high"提升加载优先级。
3. SVG优化
- 压缩SVG:用SVGO工具去除
pic-lob.svg中的冗余代码(注释、无用属性等),可减小30%-70%的体积 - 内联SVG:如果SVG尺寸小,直接将SVG代码写入CSS,避免额外网络请求:
.bg-hero { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>'); }
- 若作为背景图加载慢,也可改用
<img>标签加载SVG并启用懒加载。
4. 配置Vercel缓存策略
在项目根目录创建vercel.json,设置静态资源的长期缓存,让浏览器复用缓存文件,避免重复请求:
{ "headers": [ { "source": "/(.*\\.(png|jpg|jpeg|webp|avif|svg))", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } ] } ] }
5. 渐进式加载(可选)
用低质量占位图(LQIP)优化用户感知:
- 生成
check.png的小尺寸模糊版本(如10x10像素,压缩后几KB),命名为check-lqip.png - 先加载占位图,再替换为原图:
import { useState, useEffect } from 'react'; export default function MyImg({ containerStyles }: ImgProps) { const [src, setSrc] = useState("/check-lqip.png"); useEffect(() => { const img = new Image(); img.src = "/check.webp"; img.onload = () => setSrc("/check.webp"); }, []); return ( <div className={`${containerStyles}`}> <img src={src} alt="Picture" className="object-contain" loading="lazy" /> </div> ) } interface ImgProps { containerStyles: string; }
6. 预加载关键资源
如果图片是首屏必须显示的,在index.html中添加预加载标签:
<link rel="preload" href="/check.webp" as="image" type="image/webp">
内容的提问来源于stack exchange,提问作者shiningStar
相关产品推荐
相关产品推荐

