Next.js引入Agora SDK后刷新页面触发“ReferenceError: window is not defined”错误的解决求助
我明白你卡在这里有多难受!这个问题的根源很明确:Agora RTC SDK依赖浏览器环境的window对象,但Next.js在服务器端渲染(SSR)阶段并没有这个对象,所以当页面刷新时,服务器端执行到Agora的初始化代码就会报错。你尝试用next/dynamic是对的,但可能是使用方式不对——因为createClient和createMicrophoneAudioTrack是需要执行的函数,直接动态导入整个模块的话,服务器端还是会尝试执行这些代码。
下面给你两种可行的解决方案,根据你的Next.js版本选择:
方案一:用客户端组件隔离Agora逻辑(Next.js 13+ App Router)
如果你的项目用的是App Router,最简单的方式是用'use client'指令把Agora相关的代码限定在客户端执行:
- 创建一个客户端专属的Agora配置文件(比如
agora-providers.jsx):
'use client'; import { createClient, createMicrophoneAudioTrack } from "agora-rtc-react"; const appId = "***"; const token = null; const config = { mode: "rtc", codec: "vp8", appId: appId, token: token }; export const useClient = createClient(config); export const useMicrophoneAudioTrack = createMicrophoneAudioTrack(); export const channelName = "Main";
- 在你的
room.jsx中导入并使用:
'use client'; import { useClient, useMicrophoneAudioTrack, channelName } from './agora-providers'; export default function Room() { const client = useClient(); const { ready, track } = useMicrophoneAudioTrack(); // 你的页面逻辑和渲染代码 return ( <div> {/* 渲染内容 */} </div> ); }
'use client'会告诉Next.js这个组件只能在客户端执行,服务器端不会渲染它,自然就不会触发window相关的错误。
方案二:用next/dynamic禁用SSR(适用于所有Next.js版本)
如果是Pages Router,或者你更习惯用动态导入,可以把使用Agora hooks的逻辑放到单独组件里,再动态导入这个组件并禁用SSR:
- 创建
AgoraRoomContent.jsx组件:
import { useClient, useMicrophoneAudioTrack, channelName } from './settings'; export default function AgoraRoomContent() { const client = useClient(); const { ready, track } = useMicrophoneAudioTrack(); // 你的组件逻辑 return ( <div> {/* 渲染内容 */} </div> ); }
- 修改
settings.js,确保初始化只在客户端执行:
import { createClient, createMicrophoneAudioTrack } from "agora-rtc-react"; const appId = "***"; const token = null; const config = { mode: "rtc", codec: "vp8", appId: appId, token: token }; // 只在客户端环境下初始化Agora hooks let useClient; let useMicrophoneAudioTrack; export const channelName = "Main"; if (typeof window !== 'undefined') { useClient = createClient(config); useMicrophoneAudioTrack = createMicrophoneAudioTrack(); } export { useClient, useMicrophoneAudioTrack };
- 在
room.jsx中动态导入组件:
import dynamic from 'next/dynamic'; // 动态导入组件,禁用SSR const AgoraRoomContent = dynamic(() => import('./AgoraRoomContent'), { ssr: false, loading: () => <div>Loading Agora components...</div> }); export default function Room() { return <AgoraRoomContent />; }
为什么之前的next/dynamic会报错?
你之前直接动态导入settings.js的问题在于:即使动态导入,settings.js里的代码还是会在服务器端被执行,createClient和createMicrophoneAudioTrack会尝试访问window导致错误。上面的方案要么把初始化逻辑放到客户端组件里,要么用typeof window !== 'undefined'判断,确保这些代码只在浏览器里运行。
这样修改后,不管是首次进入还是刷新页面,都不会再出现window is not defined的错误了!
内容的提问来源于stack exchange,提问作者Jeoffrey Duke

