Next.js项目中如何修复EventSource not defined错误
Next.js项目调用EventSource报
EventSource is not defined问题 问题背景
- 正在Next.js项目中接入
SSE Events,已获取到可访问SSE事件的对应URL - 初始实现代码如下:
const ssEvents = new EventSource(stream_url,{withCredentials:false}) ssEvents.addEventListener("participant.details", (e)=>{ var data = JSON.parse(e.data) console.log(data) })
- 运行时抛出
EventSource not defined错误:编写代码时TypeScript可正常识别EventSource类型、也可正常调用.addEventListener方法,但实际执行就触发报错,不确定是否遗漏配置、是否需要引入额外依赖 - 报错栈信息:
error - pages/index.tsx (55:19) @ Home ReferenceError: EventSource is not defined 54 | > 55 | const ssEvents = new EventSource(stream_url,{withCredentials:false}) | ^ 56 |
- 项目
tsconfig.json配置如下:
{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true }, "include": [ "next-env.d.ts", "**/*.ts", "**/*.tsx", "src/utils/analytics/index.js", "react-google-captcha.d.ts", "src/providers/apollo.tsx", "src/providers/apollo-client.ts", "src/utils/wallet/walletManager.js" ], "exclude": ["node_modules"] }
问题根因
EventSource是浏览器端专属Web API,仅存在于浏览器全局上下文,Node.js服务端环境没有该全局对象。Next.js默认会对页面做服务端渲染(SSR),当前代码在服务端渲染阶段就执行了new EventSource()逻辑,直接触发未定义错误。
tsconfig中配置了dom类型库,仅能让TypeScript在编译阶段识别浏览器API的类型,不会给服务端运行时注入对应的实现,所以写代码时不会报类型错误,但运行时会报错。
修复方案
根据使用场景选对应方案即可:
- 客户端使用SSE场景(绝大多数情况):把EventSource初始化、事件监听的逻辑放到仅客户端执行的钩子中
- Pages Router函数组件:将逻辑放到
useEffect回调中,该回调仅会在客户端hydration完成后执行,不会在服务端运行,示例代码:useEffect(() => { const ssEvents = new EventSource(stream_url, { withCredentials: false }) const handleParticipantDetails = (e: MessageEvent) => { const data = JSON.parse(e.data) console.log(data) } ssEvents.addEventListener("participant.details", handleParticipantDetails) // 组件卸载时清理监听、关闭连接,避免内存泄漏 return () => { ssEvents.removeEventListener("participant.details", handleParticipantDetails) ssEvents.close() } }, [stream_url]) - Pages Router类组件:将逻辑放到
componentDidMount生命周期中执行 - App Router场景:使用EventSource的组件需要在文件顶部添加
'use client'指令标记为客户端组件,再配合useEffect存放相关逻辑
- Pages Router函数组件:将逻辑放到
- 服务端场景需要调用SSE:安装Node.js环境兼容的SSE客户端依赖
eventsource,TypeScript项目额外安装类型包@types/eventsource,引入后使用即可,不要调用浏览器内置的EventSource。
内容的提问来源于stack exchange,提问作者xerax
相关产品推荐
相关产品推荐

