Next.js 14中Socket.io-client连接报错:isValidUTF8不是函数求解决
解决Next.js 14中Socket.io-client连接时的isValidUTF8错误
错误信息
uncaughtException: TypeError: isValidUTF8 is not a function at module.exports.isValidUTF8 (webpack-internal:///(ssr)/./node_modules/ws/lib/validation.js:120:53) at Receiver.dataMessage (webpack-internal:///(ssr)/./node_modules/ws/lib/receiver.js:517:43) at Receiver.getData (webpack-internal:///(ssr)/./node_modules/ws/lib/receiver.js:446:17) at Receiver.startLoop (webpack-internal:///(ssr)/./node_modules/ws/lib/receiver.js:148:22) at Receiver._write (webpack-internal:///(ssr)/./node_modules/ws/lib/receiver.js:83:10) at writeOrBuffer (node:internal/streams/writable:392:12) at _write (node:internal/streams/writable:333:10) at Writable.write (node:internal/streams/writable:337:10) at Socket.socketOnData (webpack-internal:///(ssr)/./node_modules/ws/lib/websocket.js:1272:35) at Socket.emit (node:events:514:28) at addChunk (node:internal/streams/readable:324:12) at readableAddChunk (node:internal/streams/readable:297:9) at Readable.push (node:internal/streams/readable:234:10) at TCP.onStreamRead (node:internal/stream_base_commons:190:23) at TCP.callbackTrampoline (node:internal/async_hooks:130:17)
项目代码
app/page.js
'use client'; import { socket } from '@/app/socket'; import { useEffect, useMemo, useState } from 'react'; const Home = () => { useEffect(() => { const onNewConnection = async () =>{}; socket.on('newConnection', onNewConnection); return () => { socket.disconnect(); }; }, []); useEffect(() => { const onNewTrace = () => {}; const onExpiredTrace = () => {}; socket.on('newTrace', onNewTrace); socket.on('expiredTrace', onExpiredTrace); }, [socket]); }; export default Home;
app/socket.js
import { io } from 'socket.io-client'; export const socket = io('http://0.0.0.0:8083/');
解决方案
这个错误源于Socket.io依赖的ws库在Next.js的SSR环境中,调用Node.js内置的isValidUTF8方法时出现兼容问题,核心是WebSocket客户端逻辑被意外在服务器端执行了。以下是几种可行的解决方法:
1. 确保Socket仅在客户端初始化
修改socket.js,判断环境后再创建Socket实例,避免服务器端执行WebSocket初始化:
import { io } from 'socket.io-client'; // 只在浏览器环境创建Socket实例 export const getSocket = () => { if (typeof window === 'undefined') { return null; } return io('http://0.0.0.0:8083/'); };
然后在page.js中用useMemo初始化Socket,并添加事件监听的清理逻辑(避免内存泄漏):
'use client'; import { getSocket } from '@/app/socket'; import { useEffect, useMemo } from 'react'; const Home = () => { const socket = useMemo(() => getSocket(), []); useEffect(() => { if (!socket) return; const onNewConnection = () => {}; socket.on('newConnection', onNewConnection); // 组件卸载时移除监听并断开连接 return () => { socket.off('newConnection', onNewConnection); socket.disconnect(); }; }, [socket]); useEffect(() => { if (!socket) return; const onNewTrace = () => {}; const onExpiredTrace = () => {}; socket.on('newTrace', onNewTrace); socket.on('expiredTrace', onExpiredTrace); // 组件卸载时移除监听 return () => { socket.off('newTrace', onNewTrace); socket.off('expiredTrace', onExpiredTrace); }; }, [socket]); return <div>Home Page</div>; }; export default Home;
2. 调整Next.js Webpack配置
在next.config.js中添加Webpack配置,让服务器端忽略ws库的打包,客户端环境下禁用相关Node.js依赖:
/** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config, { isServer }) => { if (isServer) { // 服务器端将ws标记为外部依赖,避免Webpack处理 config.externals.push('ws'); } else { // 客户端环境下禁用ws依赖的Node.js模块 config.resolve.fallback = { ...config.resolve.fallback, ws: false, bufferutil: false, utf-8-validate: false, }; } return config; }, }; module.exports = nextConfig;
3. 更新依赖版本
确保socket.io-client和ws版本兼容,升级到最新稳定版:
npm install socket.io-client@latest # 或者指定兼容的ws版本 npm install ws@8.14.2
内容的提问来源于stack exchange,提问作者Lin BM
相关产品推荐
相关产品推荐

