Next.js-TypeScript中Background组件mouseover变色时window未定义问题
解决Next.js部署Vercel时"window is not defined"问题
1. 修正动态导入的正确方式
你之前用next/dynamic没生效,大概率是没加ssr: false参数,这个参数会强制组件只在客户端渲染,完全避开服务端环境:
import dynamic from 'next/dynamic'; // 动态导入Background组件,禁用SSR const Background = dynamic(() => import('../components/Background'), { ssr: false, loading: () => <div className="bg-placeholder"></div> // 可选加个加载占位 });
注意:页面组件里直接用这个动态导入的Background,别在服务端执行的代码(比如getServerSideProps、页面顶层逻辑)里引用它。
2. 组件内部把window相关逻辑放进useEffect
就算用了动态导入,组件初始化时直接访问window还是会炸,把所有依赖window的代码(比如事件监听、获取视窗尺寸、SVG里的动态逻辑)都放进useEffect——这个钩子只会在客户端执行:
import { useEffect, useState } from 'react'; const Background = () => { const [hoverColor, setHoverColor] = useState('#ffffff'); useEffect(() => { // 这里随便用window,服务端根本不会执行这段 const handleMouseHover = () => { setHoverColor('#e0e0e0'); // 你的变色逻辑 }; const handleMouseLeave = () => { setHoverColor('#ffffff'); }; const bgElement = document.getElementById('bg-container'); if (bgElement) { bgElement.addEventListener('mouseenter', handleMouseHover); bgElement.addEventListener('mouseleave', handleMouseLeave); } // 记得清理事件监听 return () => { if (bgElement) { bgElement.removeEventListener('mouseenter', handleMouseHover); bgElement.removeEventListener('mouseleave', handleMouseLeave); } }; }, []); return ( <div id="bg-container" style={{ backgroundColor: hoverColor }}> {/* 你的SVG内容,别在SVG里写内联JS,把动态逻辑移到React里 */} <svg viewBox="0 0 100 100">...</svg> </div> ); }; export default Background;
如果你的SVG里有内联JavaScript,直接删掉,把逻辑转成React的状态控制——服务端渲染时会忽略SVG里的内联JS,但生产环境打包可能会把这些代码提前执行,导致报错。
3. 排查第三方库的锅
如果你的组件依赖了第三方库,先确认这个库是不是在初始化时就访问window。要是的话,把库的导入也放进useEffect里延迟加载:
useEffect(() => { // 客户端才加载依赖window的库 import('some-lib-that-needs-window').then((lib) => { // 在这里用库的功能 }); }, []);
4. 最后检查Vercel部署
先本地跑next build && next start模拟生产环境,看看会不会报错——如果本地生产环境没问题,Vercel部署时清空缓存重新构建一次,有时候旧缓存会导致代码没更新。
内容的提问来源于stack exchange,提问作者Chibuzo Odigbo
相关产品推荐
相关产品推荐

