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

React Vite环境下SimplePeer实例化报错:Cannot read properties of undefined

问题描述

我参考非React+Vite环境的多人会议Demo编写代码,逻辑与Demo完全一致,但运行时出现以下报错:

stream_readable.js:178 Uncaught (in promise) TypeError: 无法读取未定义的属性(读取'call')
    at Peer.Readable (_stream_readable.js:178:10)
    at new Duplex (_stream_duplex.js:51:12)
    at new Peer (index.js:37:5)
    at createPeer (createroom.jsx:72:16)
    at createroom.jsx:43:28
    at Array.forEach (<anonymous>)
    at Socket2.<anonymous> (createroom.jsx:42:17)
    at Emitter.emit (index.mjs:136:20)
    at Socket2.emitEvent (socket.js:498:20)
    at Socket2.onevent (socket.js:485:18)

报错指向new Peer()(即new SimplePeer())语句。我尝试使用vite-compatible-simple-peer替换,问题仍未解决。

相关代码片段

createPeer与addPeer函数

function createPeer(userToSignal, callerID, stream) {
  const peer = new SimplePeer ({
    initiator: true,
    trickle:false,
    iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    stream: stream, 
  });

  peer.on("signal", signal => {
    socketRef.current.emit("sending signal", { userToSignal, callerID, signal })
  });

  return peer;
}

function addPeer(incomingSignal, callerID, stream) {
  const peer = new SimplePeer ({
    initiator: false,
    trickle:false,
    iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    stream: stream, 
  });

vite.config.js配置

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  define: {
    global: {},
  }
  
});

完整客户端代码

import { useEffect, useRef, useState } from "react";
import "./createRoom.css";
import io from "socket.io-client";
import { useParams } from "react-router-dom";
import  SimplePeer  from "simple-peer";
  const Video = (props) => {
    const ref = useRef();

    useEffect(() => {
      if (props.peer) {
        props.peer.on("stream", stream => {
          ref.current.srcObject = stream;
        });
      }
    }, []);

  return (
    <video
      style={{ width: "100%", transform: "rotateY(180deg)" }}
      ref={ref}
      autoPlay
      playsInline
    ></video>
  );
};

export default function CreateRoom({ username }) {
  const [peers, setPeers] = useState([]);
  const socketRef = useRef();
  const userVideo = useRef();
  const peersRef = useRef([]);
  const { id } = useParams();
  const roomID = id;

  useEffect(() => {
    socketRef.current = io.connect("http://localhost:3000/");
    navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
      userVideo.current.srcObject = stream;
      socketRef.current.emit("join room", roomID);
      socketRef.current.on("all users", users => {
          const peers = [];
          users.forEach(userID => {
              const peer = createPeer(userID, socketRef.current.id, stream);
              peersRef.current.push({
                  peerID: userID,
                  peer,
              })
              peers.push(peer);
          })
          setPeers(peers);
      })

      socketRef.current.on("user joined", payload => {
        console.log(payload);
          const peer = addPeer(payload.signal, payload.callerID, stream);
          peersRef.current.push({
              peerID: payload.callerID,
              peer,
          })

          setPeers(users => [...users, peer]);
      });

      socketRef.current.on("receiving returned signal", payload => {
          const item = peersRef.current.find(p => p.peerID === payload.id);
          item.peer.signal(payload.signal);
      });
  })
}, [roomID]);

function createPeer(userToSignal, callerID, stream) {
  const peer = new SimplePeer ({
    initiator: true,
    trickle:false,
    iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    stream: stream, 
  });

  peer.on("signal", signal => {
    socketRef.current.emit("sending signal", { userToSignal, callerID, signal })
  });

  return peer;
}

function addPeer(incomingSignal, callerID, stream) {
  const peer = new SimplePeer ({
    initiator: false,
    trickle:false,
    iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    stream: stream, 
  });

  peer.on("signal", signal => {
      socketRef.current.emit("returning signal", { signal, callerID })
  });

  peer.on("stream", stream => {
      const item = {
          peerID: callerID,
          peer,
          stream,
      };
      peersRef.current.push(item);
      setPeers(users => [...users, peer]);
  });

  peer.signal(incomingSignal);

  return peer;
}

  return (
    <div className="video-wrap">
      <span style={{ position: "absolute", top: "1px", left: "1px" }}>
        {username}
      </span>
      <video
        style={{ width: "100%", transform: "rotateY(180deg)" }}
        ref={userVideo}
        autoPlay
        playsInline
      ></video>
      {peers.map((peer, index) => {
        return <Video key={index} peer={peer} />;
      })}
    </div>
  );
}
解决方法

这个报错是因为SimplePeer依赖Node.js的stream模块,而Vite浏览器环境未原生提供该模块,且你当前的global配置不正确,导致模块初始化失败。按以下步骤修复:

  1. 安装polyfill依赖
    在项目中安装浏览器环境的stream和buffer兼容包:
npm install stream-browserify buffer
  1. 修改vite.config.js配置
    更新配置,添加别名映射、正确配置global并优化依赖:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      stream: 'stream-browserify',
      buffer: 'buffer',
    },
  },
  define: {
    global: 'window',
  },
  optimizeDeps: {
    include: ['stream-browserify', 'buffer'],
  },
});
  1. 在项目入口引入polyfill
    在main.jsx/main.tsx顶部添加以下代码:
import { Buffer } from 'buffer';
import 'stream-browserify';

window.Buffer = Buffer;
  1. 替换为官方SimplePeer包
    卸载兼容包,使用官方包即可:
npm uninstall vite-compatible-simple-peer
npm install simple-peer

完成以上修改后,SimplePeer就能在Vite+React环境中正常初始化,报错即可解决。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 22:25:06