Next.js中/pages/api下的game.js API文件未执行问题排查
问题:Next.js API路由中的WebSocket代码未执行,无日志输出
我尝试使用WebSocket构建一个简单网站,问题并非出在WebSocket本身。我的/pages/api目录下有一个名为game.js的端点,代码如下所示,但执行npm run dev时该代码完全未运行,甚至最上方的console.log('I AM EXECUTING')都未输出到控制台。控制台无任何报错,应用已正常启动,但看不到该日志信息,请问可能是什么原因导致的?
const WebSocket = require('ws'); console.log('I AM EXECUTING'); const wss = new WebSocket.Server({ noServer: true }); wss.on('listening', () => { console.log('listening'); }); wss.on('connection', (ws) => { console.log('Client connected'); ws.on('message', (message) => { console.log(`Received message: ${message}`); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); }); ws.on('close', () => { console.log('Client disconnected'); }); }); export default function handler(req, res) { if (req.headers.upgrade !== 'websocket') { res.status(400).send('Expected WebSocket request'); return; } const key = req.headers['sec-websocket-key']; wss.handleUpgrade(req, req.socket, key, onUpgrade); function onUpgrade(error) { if (error) { console.error('WebSocket upgrade failed:', error.message); res.end(); return; } wss.emit('connection', req.socket); } }
可能的原因与解决方案
1. Next.js API路由是按需加载的
Next.js的/pages/api目录下的文件属于API路由,这类文件只有当对应的端点被客户端请求时才会执行,启动npm run dev时不会自动运行模块内的代码。
验证方法:启动应用后,用浏览器或curl访问http://localhost:3000/api/game,此时控制台应该会输出I AM EXECUTING(虽然接口会返回400错误,因为这是WebSocket升级请求,但代码会被触发执行)。
2. WebSocket Server初始化方式存在问题
原代码直接在模块顶层创建WebSocket Server实例,在Next.js开发模式下,热重载可能导致多次初始化;同时,若未触发API请求,模块不会被加载,自然不会执行顶层代码。
修复方案:使用单例模式确保WebSocket Server只初始化一次:
const WebSocket = require('ws'); // 用全局变量保存单例实例 let wss; console.log('I AM EXECUTING'); if (!wss) { wss = new WebSocket.Server({ noServer: true }); wss.on('listening', () => { console.log('listening'); }); wss.on('connection', (ws) => { console.log('Client connected'); ws.on('message', (message) => { console.log(`Received message: ${message}`); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); }); ws.on('close', () => { console.log('Client disconnected'); }); }); } export default function handler(req, res) { if (req.headers.upgrade !== 'websocket') { res.status(400).send('Expected WebSocket request'); return; } // 修正handleUpgrade的回调参数 wss.handleUpgrade(req, req.socket, req.headers['sec-websocket-key'], (ws) => { wss.emit('connection', ws); }); }
3. 原代码中handleUpgrade的回调逻辑错误
原代码里的onUpgrade函数参数错误,handleUpgrade的第四个回调参数是升级后的WebSocket对象,而非错误。错误处理应该通过监听WebSocket实例的error事件或try/catch实现,原写法会导致连接逻辑失效。
内容的提问来源于stack exchange,提问作者alEN
相关产品推荐
相关产品推荐

