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

Next.js 13 App Router构建报错:navigator is not defined

解决Next.js构建时ReferenceError: navigator is not defined的问题

问题分析

即使页面添加了'use client'标记,Next.js执行next build时仍会对组件进行服务器端预渲染(或静态生成),组件的顶层代码会在服务器环境中执行,而服务器环境不存在navigator这个浏览器专属对象,因此触发报错。npm run dev时无异常是因为开发模式下更多依赖客户端即时渲染,不会严格执行服务器端预检查。

解决方案

1. 将依赖navigator的代码放入useEffect

useEffect的回调函数仅在客户端渲染完成后执行,完全避免服务器端执行浏览器专属API:

'use client';

import { useEffect, useState } from 'react';

export default function VideoChatPage() {
  const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);

  useEffect(() => {
    // 仅在客户端执行媒体流获取逻辑
    const fetchMediaStream = async () => {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: true,
          audio: true
        });
        setMediaStream(stream);
      } catch (error) {
        console.error('获取媒体流失败:', error);
      }
    };

    fetchMediaStream();

    // 组件卸载时释放媒体流
    return () => {
      if (mediaStream) {
        mediaStream.getTracks().forEach(track => track.stop());
      }
    };
  }, []);

  return (
    <div>
      {mediaStream && (
        <video
          autoPlay
          muted
          ref={el => el && (el.srcObject = mediaStream)}
        />
      )}
    </div>
  );
}

2. 用条件判断包裹navigator相关代码

如果必须在顶层执行部分逻辑,可通过typeof navigator !== 'undefined'确保仅在客户端环境运行:

'use client';

// 顶层条件判断,避免服务器端执行
const isClient = typeof navigator !== 'undefined';

export default function VideoChatPage() {
  useEffect(() => {
    if (isClient) {
      // 执行依赖navigator的逻辑
    }
  }, []);

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

关键注意点

  • 不要在组件顶层直接调用navigator.mediaDevices或其他浏览器专属API,即使加了'use client'也不行
  • 所有依赖浏览器环境的逻辑,都要放到useEffect、useLayoutEffect或客户端事件回调(如点击事件)中
  • 组件卸载时记得释放媒体资源,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:25:06