Next.js如何实现页面展示前预加载数据并添加加载器
Next.js 重资源页面预加载实现方案
你原来写的固定2秒延时方案有本质缺陷:网络环境好的时候用户会白白等待固定时长,拖慢首屏体验;网络差的时候2秒倒计时结束资源还没加载完成,页面展示后还是会出现图片空白、布局偏移的问题,根本达不到“资源全加载完再展示页面”的需求。
正确的实现逻辑是以资源实际加载状态为判断依据,不硬编码等待时长,具体实现如下。
核心实现思路
- 页面初始状态默认展示自定义加载器
- 页面挂载后,并行拉取页面所需的接口数据、监听所有首屏图片的加载状态
- 所有核心资源加载完成后,再切换展示正式页面内容
- 可配置极短的最小加载时长(通常300ms即可),避免资源加载过快时加载器闪一下就消失的体验问题
可直接复用的代码实现
import { useState, useEffect } from 'react' import PageLayout from '@/components/PageLayout' import AboutHero from '@/components/AboutHero' const AboutPage = () => { const [pageReady, setPageReady] = useState(false) useEffect(() => { // 加载页面接口数据 const loadCoreData = async () => { // 替换成你自己的页面数据请求逻辑,比如拉取关于页的文案、配置信息 // const pageData = await fetch('/api/about').then(res => res.json()) } // 等待所有首屏图片加载完成 const waitForImagesLoad = () => { return new Promise((resolve) => { const allImgs = Array.from(document.images) const pendingImgs = allImgs.filter(img => !img.complete) // 没有待加载图片直接返回 if (pendingImgs.length === 0) return resolve(true) let loadedCount = 0 const onSingleImgDone = () => { loadedCount++ if (loadedCount === pendingImgs.length) resolve(true) } pendingImgs.forEach(img => { // 加载成功、失败都标记为完成,避免单张图异常卡住整个页面 img.addEventListener('load', onSingleImgDone, { once: true }) img.addEventListener('error', onSingleImgDone, { once: true }) }) }) } const initPage = async () => { await loadCoreData() await waitForImagesLoad() // 最小展示300ms加载器,避免闪烁 await new Promise(resolve => setTimeout(resolve, 300)) setPageReady(true) } initPage() }, []) return pageReady ? ( <PageLayout headProps={{ title: "We are Laugh - About" }}> <AboutHero /> </PageLayout> ) : ( // 替换成你的自定义加载器组件 <div className="fixed inset-0 flex items-center justify-center bg-white"> <div>页面加载中...</div> </div> ) } export default AboutPage
关键优化注意事项
- 如果你使用Next.js自带的
next/image组件,记得给首屏可见的图片加上priority属性,标记为高优先级加载资源,避免被默认懒加载策略影响,导致首屏图片没被提前加载 - 不要用
window.onload事件作为页面就绪的判断标准,这个事件会等待页面所有第三方脚本、埋点资源、非首屏资源全部加载完才触发,会让用户等待不必要的时长 - 图片加载失败一定要做兜底处理,不要因为单张资源异常就把用户永久卡在加载页
- 如果你用Next.js 13+的App Router模式,可以配合内置的
loading.tsx文件和路由预加载能力实现,在用户点击路由跳转时就开始加载目标页资源,资源就绪后再完成路由切换,体验更流畅
内容的提问来源于stack exchange,提问作者Emiliano
相关产品推荐
相关产品推荐

