NextJS+TypeScript静态站点如何异步预加载展示图库的原图资源
解决方案
核心原理
浏览器会自动缓存已下载的静态资源,我们可以在首屏渲染完成后,低优先级异步加载所有原图资源,用户点击缩略图时会直接读取本地缓存,无需等待下载。
具体实现
在现有组件中加入预加载逻辑,利用requestIdleCallback在浏览器空闲时执行,不会阻塞首屏渲染:
修改后的完整组件代码
import { useEffect } from 'react' import { Grid, Paper } from "@mui/material"; import Image from 'next/image'; import IMAGES from './galleryImages'; import { SRLWrapper, useLightbox } from "simple-react-lightbox"; import CustomImageLoader from '../imageLoader'; const options = { settings: { slideAnimationType: 'fade', disablePanzoom: false, disableWheelControls: false, boxShadow: 'none' }, buttons: { showAutoplayButton: false, showDownloadButton: false, showFullscreenButton: false, showThumbnailsButton: true }, thumbnails: { showThumbnails: true }, caption: { showCaption: false }, progressBar: { showProgressBar: false } } const ShowCase = () => { const { openLightbox, closeLightbox } = useLightbox() // 新增预加载逻辑 useEffect(() => { const preloadAllOriginalImages = () => { IMAGES.original.forEach(imgItem => { const tempImg = new Image() // 若IMAGES.original的路径已通过loader处理,可直接赋值img.src = imgItem.src tempImg.src = CustomImageLoader({ src: imgItem.src, width: 0, quality: 100 }) }) } // 浏览器空闲时执行,不阻塞首屏 if ('requestIdleCallback' in window) { window.requestIdleCallback(preloadAllOriginalImages) } else { // 兼容低版本浏览器,延迟1秒执行保证首屏渲染完成 setTimeout(preloadAllOriginalImages, 1000) } }, []) return ( <Grid container spacing={1} item xs={11} lg={8} alignItems="flex-start" justifyContent="center"> <SRLWrapper elements={IMAGES.original} options={options} /> {IMAGES.thumbnails.map((image, index) => ( <Grid style={{ cursor: 'pointer' }} item xs={2} key={image.src}> <Paper elevation={5}> <Image loader={CustomImageLoader} onClick={() => openLightbox(index)} src={image} layout="responsive" sizes="50vw" /> </Paper> </Grid> ))} </Grid> ) } export default ShowCase
大体积/多数量原图优化方案
如果原图总大小超过10MB或者数量超过20张,一次性全预加载会占用过多带宽,可改用hover预加载方案:
// 仅修改Image组件部分,hover时预加载对应原图 <Image loader={CustomImageLoader} onClick={() => openLightbox(index)} onMouseEnter={() => { const tempImg = new Image() tempImg.src = CustomImageLoader({ src: IMAGES.original[index].src, width: 0, quality: 100 }) }} src={image} layout="responsive" sizes="50vw" />
内容的提问来源于stack exchange,提问作者jean-daniel kuenzi
相关产品推荐
相关产品推荐

