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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:10:07