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

NextJS TypeScript报错:ReferenceError: document is not defined 求助

解决Next.js TypeScript项目中document is not defined错误

问题原因

Next.js App Router 默认将组件视为服务端组件(Server Component),服务端运行环境中不存在document、window这类浏览器专属的DOM API,直接在组件顶层访问这些API会抛出ReferenceError。

解决方案

以下是几种可行的解决方式,根据你的组件场景选择:

1. 将组件标记为客户端组件

在StarrySky.tsx文件顶部添加'use client'指令,强制组件在浏览器端渲染,此时就能正常访问document和window:

'use client';

import { useEffect, useState } from 'react';

export default function StarrySky() {
  const [vw, setVw] = useState(0);

  useEffect(() => {
    // 初始化视口宽度
    const updateViewportWidth = () => {
      const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
      setVw(width);
    };
    
    updateViewportWidth();
    // 监听窗口大小变化,实时更新
    window.addEventListener('resize', updateViewportWidth);
    
    // 组件卸载时移除监听
    return () => window.removeEventListener('resize', updateViewportWidth);
  }, []);

  // 后续业务逻辑使用vw变量
  return <div className="starry-sky">...</div>;
}

适用场景:组件本身需要交互、依赖浏览器API,或大部分逻辑在客户端执行。

2. 动态导入组件并禁用SSR

如果不想将整个组件改为客户端组件,可通过Next.js的dynamic导入函数,指定该组件仅在客户端渲染:

// 在resume/page.tsx中修改导入方式
import dynamic from 'next/dynamic';

// 禁用SSR,组件仅在浏览器加载
const StarrySky = dynamic(() => import('../StarrySky'), { ssr: false });

export default function ResumePage() {
  return (
    <div>
      <StarrySky />
      {/* 页面其他服务端渲染内容 */}
    </div>
  );
}

适用场景:组件仅需客户端渲染,而页面其余部分保持服务端渲染以优化性能。

3. 条件判断浏览器环境

如果只是局部代码需要访问浏览器API,可通过typeof window !== 'undefined'判断环境,确保代码仅在浏览器执行:

// StarrySky.tsx中
import { useEffect, useState } from 'react';

export default function StarrySky() {
  const [vw, setVw] = useState(0);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const updateWidth = () => {
        const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
        setVw(width);
      };
      updateWidth();
      window.addEventListener('resize', updateWidth);
      return () => window.removeEventListener('resize', updateWidth);
    }
  }, []);

  return <div>...</div>;
}

适用场景:组件大部分逻辑可在服务端执行,仅小部分依赖浏览器API。

注意事项

  • 避免在组件顶层直接访问document/window:即使是客户端组件,也建议将这类代码放在useEffect或事件回调中,确保DOM已准备就绪。
  • 客户端组件会增加客户端负载:仅在必要时使用'use client',优先保持服务端组件以优化页面加载性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 21:30:17