如何在Nuxt生产环境中启用listen hook?
Nuxt生产环境启用listen hook并关联WebSocketServer的解决方案
你的问题出在Nuxt配置中的listen钩子仅作用于开发服务器,执行npm run build && npm run preview时启动的是Nitro生产服务器,这个钩子不会被触发。要在生产环境生效,需要改用Nitro提供的server:listen钩子,以下是两种可行方案:
方案一:在nuxt.config.ts中配置Nitro钩子
直接将原逻辑迁移到nitro.hooks下的server:listen钩子中:
// https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ nitro: { hooks: { 'server:listen'(server) { console.log(server) const yogaApp = createYoga({ graphqlEndpoint: '/api/graphql', schema: createSchema({ typeDefs: /* GraphQL */ ` type Query { hello: String } type Subscription { countdown(from: Int!): Int! } `, resolvers: { Query: { hello: () => 'world' }, Subscription: { countdown: { subscribe: async function* (_, { from }) { for (let i = from; i >= 0; i--) { await new Promise((resolve) => setTimeout(resolve, 1000)) yield { countdown: i } } } } } } }), graphiql:{ subscriptionsProtocol: "WS" } }) console.log(yogaApp.graphqlEndpoint) const wsServer = new WebSocketServer({ server, path: yogaApp.graphqlEndpoint }) useServer( { execute: (args: any) => args.rootValue.execute(args), subscribe: (args: any) => args.rootValue.subscribe(args), onSubscribe: async (ctx, msg) => { const { schema, execute, subscribe, contextFactory, parse, validate } = yogaApp.getEnveloped({ ...ctx, req: ctx.extra.request, socket: ctx.extra.socket, params: msg.payload }) const args = { schema, operationName: msg.payload.operationName, document: parse(msg.payload.query), variableValues: msg.payload.variables, contextValue: await contextFactory(), rootValue: { execute, subscribe } } const errors = validate(args.schema, args.document) if (errors.length) return errors return args } }, wsServer ) } } } })
方案二:创建服务器插件(推荐,更模块化)
在项目根目录下创建server/plugins/ws.ts文件,通过Nitro插件注册钩子:
import { createYoga, createSchema } from 'graphql-yoga' import { WebSocketServer } from 'ws' import { useServer } from 'graphql-ws/lib/use/ws' export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('server:listen', (server) => { // 原listen钩子中的逻辑完全迁移到这里 const yogaApp = createYoga({ graphqlEndpoint: '/api/graphql', schema: createSchema({ typeDefs: /* GraphQL */ ` type Query { hello: String } type Subscription { countdown(from: Int!): Int! } `, resolvers: { Query: { hello: () => 'world' }, Subscription: { countdown: { subscribe: async function* (_, { from }) { for (let i = from; i >= 0; i--) { await new Promise((resolve) => setTimeout(resolve, 1000)) yield { countdown: i } } } } } } }), graphiql:{ subscriptionsProtocol: "WS" } }) console.log(yogaApp.graphqlEndpoint) const wsServer = new WebSocketServer({ server, path: yogaApp.graphqlEndpoint }) useServer( { execute: (args: any) => args.rootValue.execute(args), subscribe: (args: any) => args.rootValue.subscribe(args), onSubscribe: async (ctx, msg) => { const { schema, execute, subscribe, contextFactory, parse, validate } = yogaApp.getEnveloped({ ...ctx, req: ctx.extra.request, socket: ctx.extra.socket, params: msg.payload }) const args = { schema, operationName: msg.payload.operationName, document: parse(msg.payload.query), variableValues: msg.payload.variables, contextValue: await contextFactory(), rootValue: { execute, subscribe } } const errors = validate(args.schema, args.document) if (errors.length) return errors return args } }, wsServer ) }) })
关键说明
- Nitro是Nuxt3的后端运行时引擎,
server:listen钩子会在开发、生产预览、生产部署三种场景下触发,完美替代原Nuxt开发服务器的listen钩子。 - 确保已安装所有依赖包:
graphql-yoga、ws、graphql-ws,若未安装可执行命令:npm install graphql-yoga ws graphql-ws
内容的提问来源于stack exchange,提问作者Adri HM
相关产品推荐
相关产品推荐

