v4IntegrationsµWebSockets.js
⚠️
This is the documentation for the old GraphQL Yoga version 4. We recommend upgrading to the latest GraphQL Yoga version 5.

Migrate to GraphQL Yoga v5

Integration with µWebSockets.js

µWebSockets.js is an alternative to Node.js’s built-in HTTP server implementation. It is much faster than Node.js’s http module as you can see in the benchmarks in the GitHub repo. Despite its name, it is not a WebSocket-only server, it does HTTP as well.

Since GraphQL Yoga is framework and environment agnostic, it supports µWebSockets.js out of the box with a simple configuration.

Installation

npm i graphql-yoga graphql uWebSockets.js@uNetworking/uWebSockets.js#v20.31.0

Example

index.ts
import { createSchema, createYoga } from 'graphql-yoga'
import { App, HttpRequest, HttpResponse } from 'uWebSockets.js'
 
interface ServerContext {
  req: HttpRequest
  res: HttpResponse
}
 
const yoga = createYoga<ServerContext>({
  schema: createSchema({
    typeDefs: /* GraphQL */ `
      type Query {
        hello: String!
      }
    `,
    resolvers: {
      Query: {
        hello: () => 'Hello world!'
      }
    }
  })
})
 
App().any('/*', yoga)

Subscriptions with WebSockets

You can also use WebSockets instead of SSE with graphql-ws;

npm i graphql-ws
index.ts
import { execute, ExecutionArgs, subscribe } from 'graphql'
import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets'
import { createSchema, createYoga, Repeater } from 'graphql-yoga'
import { App, HttpRequest, HttpResponse } from 'uWebSockets.js'
 
interface ServerContext {
  req: HttpRequest
  res: HttpResponse
}
 
export const yoga = createYoga<ServerContext>({
  schema: createSchema({
    typeDefs: /* GraphQL */ `
      type Query {
        hello: String!
      }
 
      type Subscription {
        time: String!
      }
    `,
    resolvers: {
      Query: {
        hello: () => 'Hello world!'
      },
      Subscription: {
        time: {
          subscribe: () =>
            new Repeater((push, stop) => {
              const interval = setInterval(() => {
                push({
                  time: new Date().toISOString()
                })
              }, 1000)
              stop.then(() => clearInterval(interval))
            })
        }
      }
    }
  }),
  graphiql: {
    subscriptionsProtocol: 'WS' // use WebSockets instead of SSE
  }
})
 
// yoga's envelop may augment the `execute` and `subscribe` operations
// so we need to make sure we always use the freshest instance
type EnvelopedExecutionArgs = ExecutionArgs & {
  rootValue: {
    execute: typeof execute
    subscribe: typeof subscribe
  }
}
 
const wsHandler = makeBehavior({
  execute: args => (args as EnvelopedExecutionArgs).rootValue.execute(args),
  subscribe: args => (args as EnvelopedExecutionArgs).rootValue.subscribe(args),
  onSubscribe: async (ctx, msg) => {
    const { schema, execute, subscribe, contextFactory, parse, validate } = yoga.getEnveloped(ctx)
 
    const args: EnvelopedExecutionArgs = {
      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
  }
})
 
App()
  .any('/*', yoga)
  .ws(yoga.graphqlEndpoint, wsHandler)
  .listen(() => {
    console.log(`Server is running on http://localhost:4000`)
  })

Also see our full example here.