Next.js App Router生产环境API无法返回MQTT更新数据求助
Next.js App Router生产环境下MQTT数据接口无法更新的问题
我用Next.js App Router开发的页面,通过路由API获取MQTT数据。开发环境(npm run dev)里请求api/realtimeLocation接口能返回最新的MQTT数据,但生产环境中接口始终返回初始数据,没法拿到更新后的数据,找不到问题原因。
路由文件:app/api/realtimeLocation/route.ts
import mqttSubscriber from './mqtt-subscriber' export async function GET(req: any, res: any) { const { data } = mqttSubscriber let validateData = data ? JSON.parse(data) : null try { return Response.json({ status: 'OK', data: validateData }) } catch (err) { console.error('Something wrong happen') } }
MQTT订阅文件:mqtt-subscriber.js
import * as mqtt from 'mqtt' const client = mqtt.connect(`mqtt://${process.env.NEXT_PUBLIC_IP_MQTT}:1883`, { username: 'my-user', password: 'my-password', }) // subscribe client.on('connect', () => { const topic = 'fms/liveLocations' // subscrive client.subscribe(topic, err => { if (err) { console.log(err) } else { console.log(`Subscribe to topic: ${topic}`) } }) }) client.on('error', err => console.log('MQTT Error: ', err)) const receivedData = { data: null } client.on('message', (receivedTopic, message) => { receivedData.data = message.toString() }) export default receivedData
问题原因及解决方案
核心原因
Next.js生产环境会对API路由进行静态优化或代码隔离,开发环境下代码热重载且运行在单个进程,MQTT连接和数据能持续共享;但生产环境中API路由可能被打包成无状态函数,模块初始化逻辑无法在服务器生命周期内持续生效,导致无法共享实时更新的MQTT数据。
解决方法
1. 实现MQTT客户端单例模式(推荐)
确保整个服务器生命周期内只有一个MQTT连接实例,所有请求共享该实例的实时数据:
import * as mqtt from 'mqtt' // 全局单例变量 let mqttClient = null; let receivedData = { data: null }; function initMQTTClient() { if (mqttClient) return; // 已初始化直接返回 mqttClient = mqtt.connect(`mqtt://${process.env.NEXT_PUBLIC_IP_MQTT}:1883`, { username: 'my-user', password: 'my-password', }); mqttClient.on('connect', () => { const topic = 'fms/liveLocations'; mqttClient.subscribe(topic, err => { if (err) { console.log(err); } else { console.log(`Subscribe to topic: ${topic}`); } }); }); mqttClient.on('error', err => console.log('MQTT Error: ', err)); mqttClient.on('close', () => { console.log('MQTT连接断开,正在重连...'); mqttClient = null; initMQTTClient(); }); mqttClient.on('message', (receivedTopic, message) => { receivedData.data = message.toString(); }); } // 服务器启动时初始化连接 initMQTTClient(); export default receivedData;
2. 强制API路由动态执行
在路由文件顶部添加配置,禁用静态优化,确保每次请求都执行路由逻辑:
import mqttSubscriber from './mqtt-subscriber' export const dynamic = 'force-dynamic'; // 强制动态执行,避免静态缓存 export async function GET(req: any, res: any) { const { data } = mqttSubscriber let validateData = data ? JSON.parse(data) : null try { return Response.json({ status: 'OK', data: validateData }) } catch (err) { console.error('Something wrong happen') } }
3. 验证生产环境配置
确认生产环境中NEXT_PUBLIC_IP_MQTT环境变量配置正确,服务器能正常访问MQTT服务端口(1883),避免因连接失败导致数据无法更新。
内容的提问来源于stack exchange,提问作者Rizki Ramadhan
相关产品推荐
相关产品推荐

