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

NextJS特斯拉克隆项目:背景视频加载前页面渲染问题求助

解决NextJS特斯拉克隆首页背景视频加载延迟问题

针对你遇到的生产环境下背景视频加载慢、页面内容先显示的问题,提供两种可行解决方案,同时修复onLoadedData事件不生效的问题:

方案一:视频就绪后再渲染首页内容

通过React状态管理控制内容渲染时机,确保视频加载完成后才显示首页内容:

import Navbar from './components/Navbar'
import { useContext, useState } from 'react'
import { Context } from './components/contextApi'

export default function Home() {
  const { isHovered, setIsHovered } = useContext(Context)
  const [isVideoReady, setIsVideoReady] = useState(false)

  return (
    <>
      <video
        id='video-id'
        preload='auto'
        loop={true}
        autoPlay={true}
        muted={true}
        playsInline={true}
        className='h-full w-full object-cover absolute top-0 -z-50'
        src='/main.mp4'
        onLoadedData={() => setIsVideoReady(true)}
        // 添加视频封面,提升初始加载观感
        poster='/video-poster.jpg'
      ></video>

      {/* 加载占位(可替换为特斯拉风格动画) */}
      {!isVideoReady && (
        <div className='h-screen w-full flex items-center justify-center bg-black'>
          <div className='text-white text-xl'>Loading...</div>
        </div>
      )}

      {/* 视频就绪后渲染首页内容 */}
      {isVideoReady && (
        <main className={`h-screen font-Gemito`}>
          <Navbar />

          <div className="bg-overlay h-1/2 bg-gradient-to-b from-[hsla(0,0%,0%,1)] to-transparent relative -z-20"></div>

          <div className={`main-text relative -mt-[35vh]  ${isHovered ? '-z-40' : ''} text-white text-center`}>
            <div className='text-[2.5rem] sm:mb-1 font-[600]'>Model <span className='font-Poppins font-[500]'> 3</span></div>
            <div className='sm:text-2xl text-md'>From <span className='font-Roboto text-md'> $29,740*</span></div>
            <div className='text-xs sm:text-sm font-thin'>After Federal Tax Credit & Est. Gas Savings</div>
          </div>

          <div className={`buttons ${isHovered ? '-z-40' : ''} absolute bottom-5 sm:bottom-10 w-full text-center px-4 items-center text-lg justify-center [&>*]:cursor-pointer space-y-3 sm:space-x-6 text-black flex flex-col sm:flex-row`}>
            <div className="py-2 rounded-sm px-24 bg-[#fffc] backdrop-blur-sm">Order Now</div>
            <div className="py-2 text-white rounded-sm px-24 bg-[#222222a6] backdrop-blur-sm">Demo Drive</div>
          </div>
        </main>
      )}
    </>
  )
}

之前onLoadedData失效的原因

  • NextJS服务端渲染时,视频元素在服务端不存在,事件绑定需依赖React客户端 hydration 完成(上述代码直接在video元素绑定事件,React会自动处理)
  • 视频文件体积过大导致加载超时,建议压缩视频或转成webm等高效格式
  • 浏览器缓存策略问题,可在视频URL后添加版本号(如/main.mp4?v=1)避免缓存旧资源

方案二:添加加载动画(更友好的用户体验)

若不想让用户等待完整视频加载,可显示加载动画,视频就绪后自动隐藏,同时内容正常显示:

import Navbar from './components/Navbar'
import { useContext, useState } from 'react'
import { Context } from './components/contextApi'

export default function Home() {
  const { isHovered, setIsHovered } = useContext(Context)
  const [isVideoReady, setIsVideoReady] = useState(false)

  return (
    <>
      <video
        id='video-id'
        preload='auto'
        loop={true}
        autoPlay={true}
        muted={true}
        playsInline={true}
        className='h-full w-full object-cover absolute top-0 -z-50'
        src='/main.mp4'
        onLoadedData={() => setIsVideoReady(true)}
        poster='/video-poster.jpg'
      ></video>

      {/* 全屏加载动画,视频就绪后渐隐 */}
      <div className={`fixed inset-0 bg-black z-50 flex items-center justify-center transition-opacity duration-500 ${isVideoReady ? 'opacity-0 pointer-events-none' : ''}`}>
        <div className='text-white text-xl'>Loading...</div>
        {/* 可替换为特斯拉官方Spinner动画 */}
      </div>

      {/* 首页内容始终渲染,视频就绪后渐显 */}
      <main className={`h-screen font-Gemito transition-opacity duration-500 ${isVideoReady ? 'opacity-100' : 'opacity-0'}`}>
        <Navbar />

        <div className="bg-overlay h-1/2 bg-gradient-to-b from-[hsla(0,0%,0%,1)] to-transparent relative -z-20"></div>

        <div className={`main-text relative -mt-[35vh]  ${isHovered ? '-z-40' : ''} text-white text-center`}>
          <div className='text-[2.5rem] sm:mb-1 font-[600]'>Model <span className='font-Poppins font-[500]'> 3</span></div>
          <div className='sm:text-2xl text-md'>From <span className='font-Roboto text-md'> $29,740*</span></div>
          <div className='text-xs sm:text-sm font-thin'>After Federal Tax Credit & Est. Gas Savings</div>
        </div>

        <div className={`buttons ${isHovered ? '-z-40' : ''} absolute bottom-5 sm:bottom-10 w-full text-center px-4 items-center text-lg justify-center [&>*]:cursor-pointer space-y-3 sm:space-x-6 text-black flex flex-col sm:flex-row`}>
          <div className="py-2 rounded-sm px-24 bg-[#fffc] backdrop-blur-sm">Order Now</div>
          <div className="py-2 text-white rounded-sm px-24 bg-[#222222a6] backdrop-blur-sm">Demo Drive</div>
        </div>
      </main>
    </>
  )
}

额外优化建议

  • 多格式支持:同时提供mp4和webm格式视频,通过<source>标签适配不同浏览器
  • 视频压缩:使用FFmpeg等工具压缩视频体积,降低加载耗时
  • 预加载调整:将preload='auto'改为preload='metadata',仅加载视频元数据减少初始请求量

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:54:54