Next.js集成YSocketIo、Tiptap与hocuspocus/server时日志无输出问题
问题描述
我在Next.js中搭建YSocketIo、Tiptap与hocuspocus/server的集成环境,协作功能能正常运行,但添加Socket路由后没有任何响应。连接成功后看不到User connected...的日志输出,也没有报错信息,请问问题出在哪?
服务器代码
import express from "express"; import { Server } from "@hocuspocus/server"; import { createServer } from "http"; import { Server as SocketServer } from "socket.io"; import { YSocketIO } from 'y-socket.io/dist/server' const host = "localhost" const port = "1234" const app = express(); const httpServer = createServer(app); const io = new SocketServer(httpServer); const collaborationServer = Server.configure({ onConnect: (context) => { console.log("User connected", context.user); } }); const ysocketio = new YSocketIO(io) ysocketio.initialize() // Listen for Socket.IO connections io.on("connection", (socket) => { console.log("Socket.IO connection established"); socket.on("disconnect", () => { console.log("Socket.IO connection disconnected"); }); socket.on("test", () => { console.log("test"); }); collaborationServer.handleConnection(socket, null, context); }); httpServer.listen(port, host, undefined, () => console.log(`Server running on port ${port}`))
Next.js页面代码
import Collaboration from "@tiptap/extension-collaboration"; import StarterKit from "@tiptap/starter-kit"; import { EditorContent, useEditor } from "@tiptap/react"; import React, { useEffect } from "react"; import { HocuspocusProvider } from "@hocuspocus/provider"; import CollaborationCursor from "@tiptap/extension-collaboration-cursor"; import Paragraph from "@tiptap/extension-paragraph"; import Document from "@tiptap/extension-document"; import Placeholder from "@tiptap/extension-placeholder"; import Text from "@tiptap/extension-text"; import * as Y from "yjs"; import { SocketIOProvider } from 'y-socket.io'; const doc = new Y.Doc() const provider = new SocketIOProvider('http://localhost:1234', 'room-name', doc, { autoConnect: true, resyncInterval: 5000, disableBc: false }); const TipTapEditor = () => { const editor = useEditor({ extensions: [ StarterKit.configure({ history: false, }), // Register the document with Tiptap Collaboration.configure({ document: doc, }), CollaborationCursor.configure({ provider, user: { name: "Cyndi", color: "#f783ac", }, }), Placeholder.configure({ placeholder: "Write something … Itll be shared with everyone else looking at this example.", }), ], }); const handleEmit = () => { console.log('emitting test'); provider.emit('test', []); } return ( <> <button onClick={handleEmit}> Test Emit </button> <EditorContent editor={editor} /> </> ); }; export default TipTapEditor;
问题分析与解决
核心问题1:context变量未定义
服务器代码的io.on("connection")回调中,调用collaborationServer.handleConnection(socket, null, context)时,context变量未声明,会导致代码静默报错,直接跳过后续逻辑,因此Hocuspocus的onConnect回调无法触发,看不到对应的日志。
核心问题2:Hocuspocus与YSocketIO的功能冲突
你同时初始化了YSocketIO和Hocuspocus的协作服务,两者都是基于Socket.IO处理Yjs文档同步的工具,会抢占Socket连接的控制权。当前协作功能正常是因为YSocketIO在工作,但Hocuspocus的连接逻辑被完全覆盖,所以它的onConnect不会执行。
修复方案(二选一)
方案1:统一使用Hocuspocus服务
移除YSocketIO相关代码,让Hocuspocus接管所有协作逻辑:
修复后的服务器代码
import express from "express"; import { Server } from "@hocuspocus/server"; import { createServer } from "http"; import { Server as SocketServer } from "socket.io"; const host = "localhost" const port = "1234" const app = express(); const httpServer = createServer(app); const io = new SocketServer(httpServer); const collaborationServer = Server.configure({ onConnect: (context) => { console.log("User connected", context.user); }, }); io.on("connection", (socket) => { console.log("Socket.IO connection established"); // 初始化上下文,可根据需求添加用户信息 const context = { user: { id: socket.id, name: "Anonymous" } }; // 交给Hocuspocus处理连接 collaborationServer.handleConnection(socket, { path: "/hocuspocus" }, context); socket.on("disconnect", () => { console.log("Socket.IO connection disconnected"); }); socket.on("test", () => { console.log("test"); }); }); httpServer.listen(port, host, undefined, () => console.log(`Server running on port ${port}`))
修复后的客户端代码
import Collaboration from "@tiptap/extension-collaboration"; import StarterKit from "@tiptap/starter-kit"; import { EditorContent, useEditor } from "@tiptap/react"; import React from "react"; import { HocuspocusProvider } from "@hocuspocus/provider"; import CollaborationCursor from "@tiptap/extension-collaboration-cursor"; import Placeholder from "@tiptap/extension-placeholder"; import * as Y from "yjs"; const TipTapEditor = () => { const doc = new Y.Doc(); const provider = new HocuspocusProvider({ url: "ws://localhost:1234/hocuspocus", name: "room-name", document: doc, }); const editor = useEditor({ extensions: [ StarterKit.configure({ history: false, }), Collaboration.configure({ document: doc, }), CollaborationCursor.configure({ provider, user: { name: "Cyndi", color: "#f783ac", }, }), Placeholder.configure({ placeholder: "Write something … It'll be shared with everyone else looking at this example.", }), ], }); const handleEmit = () => { console.log('emitting test'); // Hocuspocus Provider用send方法发送自定义消息 provider.connection.send(JSON.stringify({ type: "test" })); } return ( <> <button onClick={handleEmit}> Test Emit </button> <EditorContent editor={editor} /> </> ); }; export default TipTapEditor;
方案2:保留YSocketIO,添加自定义Socket命名空间
如果要同时使用YSocketIO和自定义事件,用命名空间区分两者的连接:
// 服务器代码:给YSocketIO指定独立命名空间 const ysocketio = new YSocketIO(io.of('/yjs')) ysocketio.initialize() // 自定义事件用默认命名空间 io.on("connection", (socket) => { console.log("Socket.IO connection established"); socket.on("test", () => { console.log("test"); }); }); // 客户端代码:连接对应命名空间 const provider = new SocketIOProvider('http://localhost:1234/yjs', 'room-name', doc, { autoConnect: true, });
内容的提问来源于stack exchange,提问作者Naclin
相关产品推荐
相关产品推荐

