为后续“web 终端”功能做前置准备。需要 WebSocket 的支持。
Next.js 创建 WebSocket 需要使用 pages router。app router 没有完整的 request 与 response 对象。
这里使用 socket.io 在 Next.js 服务端口上支持 WebSocket。
socket.io-client 作为客户端对接 WebSocket 服务。
开发
安装依赖
pnpm i socket.io socket.io-client
创建一个 pages 的 api routes
pages/api/hello.ts
import { Server as NetServer } from 'http'
import { NextApiRequest } from 'next'
import { Server as ServerIO } from 'socket.io'
import { NextApiResponseServerIO } from '@/pages/api/types'
export const config = {
api: {
bodyParser: false,
},
}
const ioHandler = (req: NextApiRequest, res: NextApiResponseServerIO) => {
if (!res.socket.server.io) {
const path = '/api/hello'
const http_server: NetServer = res.socket.server as any
const io = new ServerIO(http_server, {
path: path,
addTrailingSlash: false,
})
io.on('connection', (socket) => {
socket.on('message', (msg) => {
socket.emit('message', `server res: ${msg}`)
})
socket.on('disconnect', () => {
console.log('A user disconnected', socket.id)
socket.broadcast.emit('user server disconnection', socket.id)
})
})
res.socket.server.io = io
}
res.end()
}
export default ioHandler
这样使用 socket.io 就创建好了一个简单的 socket 服务
TypeScript 类型描述文件
page/api/types.ts
import { Server as NetServer, Socket } from 'net'
import { NextApiResponse } from 'next'
import { Server as SocketIoServer } from 'socket.io'
export type NextApiResponseServerIO = NextApiResponse & {
socket: Socket & { server: NetServer & { io: SocketIoServer } }
}
客户端,创建一个临时的对接页面
app/test-socket/page.tsx
'use client'
import React, { useRef, useState } from 'react'
import { useMount } from 'ahooks'
import { io, Socket } from 'socket.io-client'
import { Button } from 'antd'
const TestSocket: React.FC = () => {
const [message, changeMessage] = useState<string[]>([])
const socket_ref = useRef<Socket>()
useMount(() => {
const s_io = io({ path: '/api/hello', addTrailingSlash: true })
socket_ref.current = s_io
s_io.on('message', (msg) => {
changeMessage((message) => {
return [msg, ...message]
})
})
})
return (
<>
<Button
onClick={() => {
socket_ref.current?.emit('message', Date.now())
}}
>
发送
</Button>
<ul>
{message.map((text, key) => (
<li key={key}>{text}</li>
))}
</ul>
</>
)
}
export default TestSocket
每次点击“发送”按钮会将当前时间戳发送给 WebSocket,WebSocket 原封不动的将时间戳返回,并带上 server res 的前缀。
到此,Next.js 简单的实现了 WebSocket。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。