Next.js使用extendable-media-recorder-wav-encoder时Blob未定义问题
解决Next.js SSR中使用extendable-media-recorder-wav-encoder的Blob未定义与动态导入问题
问题根源
Next.js SSR阶段在Node.js环境执行代码,而Blob、MessagePort属于浏览器专属API,服务器端不存在,直接常规导入会触发Blob is not defined错误;动态导入时因类型不匹配导致报错,后续又出现connect函数无法调用的问题。
解决方案
1. 正确配置动态导入(禁用SSR+类型适配)
使用Next.js的dynamic导入,明确禁用SSR,并调整导出结构匹配类型要求:
import dynamic from 'next/dynamic'; // 动态导入编码器并禁用SSR,同时适配类型 const connectWavEncoder = dynamic( async () => { const { connect } = await import('extendable-media-recorder-wav-encoder'); // 将connect函数作为default导出,符合dynamic的Loader类型要求 return { default: connect as (port: MessagePort) => Promise<void> }; }, { ssr: false } );
2. 仅在客户端环境调用connect函数
通过useEffect确保代码只在浏览器端执行(组件挂载后):
import { useEffect } from 'react'; function AudioRecorderComponent() { useEffect(() => { const setupWavEncoder = async () => { // 确认connect函数已加载且处于客户端环境 if (typeof connectWavEncoder === 'function' && typeof MessagePort !== 'undefined') { // 替换为你的MessagePort实例 const recorderPort = /* 获取你的MessagePort对象 */; await connectWavEncoder(recorderPort); } }; setupWavEncoder(); }, []); return <div>音频录制组件</div>; } export default AudioRecorderComponent;
3. 备选方案:客户端条件导入
如果不使用dynamic,也可以通过判断客户端环境延迟导入:
import { useEffect } from 'react'; let connectEncoder: ((port: MessagePort) => Promise<void>) | undefined; // 仅在浏览器环境加载模块 if (typeof window !== 'undefined') { import('extendable-media-recorder-wav-encoder').then(module => { connectEncoder = module.connect; }); } function AudioRecorderComponent() { useEffect(() => { const setupEncoder = async () => { if (connectEncoder && recorderPort) { await connectEncoder(recorderPort); } }; setupEncoder(); }, [recorderPort]); // 组件内容... }
关键注意点
- 所有依赖浏览器API的代码必须限制在客户端执行,避免SSR阶段运行
- 动态导入时需将目标函数包装为
default导出,匹配Next.jsdynamic的类型要求 - TypeScript环境下可通过类型断言明确函数类型,避免类型错误
内容的提问来源于stack exchange,提问作者Darshan Gowda
相关产品推荐
相关产品推荐

