v3 (latest)
Integrations
Next.js

Integration with Next.js

Next.js (opens in a new tab) is a web framework that allows you to build websites very quickly and GraphQL Yoga can be integrated with Next.js easily as an API Route (opens in a new tab).

Installation

Terminal
yarn add graphql
yarn add graphql-yoga

Example

pages/api/graphql.ts
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { createYoga, createSchema } from 'graphql-yoga'
import type { NextApiRequest, NextApiResponse } from 'next'
 
export const config = {
  api: {
    // Disable body parsing (required for file uploads)
    bodyParser: false
  }
}
 
const schema = createSchema({
  typeDefs: /* GraphQL */ `
    type Query {
      greetings: String
    }
  `,
  resolvers: {
    Query: {
      greetings: () => 'This is the `greetings` field of the root `Query` type'
    }
  }
})
 
export default createYoga<{
  req: NextApiRequest
  res: NextApiResponse
}>({
  schema,
  // Needed to be defined explicitly because our endpoint lives at a different path other than `/graphql`
  graphqlEndpoint: '/api/graphql'
})

You can also check a full example on our GitHub repository here (opens in a new tab)

WebSockets for subscriptions

WebSockets cannot be used with Next.js API Routes (opens in a new tab), we therefore have to create a custom Next.js server (opens in a new tab) that will serve the GraphQL API, WebSockets and the rest of Next.js content.

Installation

Terminal
yarn add graphql
yarn add graphql-yoga
yarn add ws
yarn add graphql-ws

Example

server.js
const { createServer } = require('http')
const { WebSocketServer } = require('ws')
const { createYoga, createSchema } = require('graphql-yoga')
const { useServer } = require('graphql-ws/lib/use/ws')
const { parse } = require('url')
const next = require('next')
 
const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
 
// prepare nextjs
const app = next({ dev, hostname, port })
 
// match the route next would use if yoga was in `pages/api/graphql.ts`
const graphqlEndpoint = '/api/graphql'
 
// prepare yoga
const yoga = createYoga({
  graphqlEndpoint,
  graphiql: {
    subscriptionsProtocol: 'WS'
  },
  schema: createSchema({
    typeDefs: /* GraphQL */ `
      type Query {
        hello: String!
      }
      type Subscription {
        clock: String!
      }
    `,
    resolvers: {
      Query: {
        hello: () => 'world'
      },
      Subscription: {
        clock: {
          async *subscribe() {
            for (let i = 0; i < 5; i++) {
              yield { clock: new Date().toString() }
              await new Promise((resolve) => setTimeout(resolve, 1_000))
            }
          }
        }
      }
    }
  })
})
 
;(async () => {
  await app.prepare()
  const handle = app.getRequestHandler()
 
  // create http server
  const server = createServer(async (req, res) => {
    try {
      // Be sure to pass `true` as the second argument to `url.parse`.
      // This tells it to parse the query portion of the URL.
      const url = parse(req.url, true)
 
      if (url.pathname.startsWith(graphqlEndpoint)) {
        await yoga(req, res)
      } else {
        await handle(req, res, url)
      }
    } catch (err) {
      console.error(`Error while handling ${req.url}`, err)
      res.writeHead(500).end()
    }
  })
 
  // create websocket server
  const wsServer = new WebSocketServer({ server, path: graphqlEndpoint })
 
  // prepare graphql-ws
  useServer(
    {
      execute: (args) => args.rootValue.execute(args),
      subscribe: (args) => args.rootValue.subscribe(args),
      onSubscribe: async (ctx, msg) => {
        const { schema, execute, subscribe, contextFactory, parse, validate } =
          yoga.getEnveloped(ctx)
 
        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
  )
 
  await new Promise((resolve, reject) =>
    server.listen(port, (err) => (err ? reject(err) : resolve()))
  )
 
  console.log(`
> App started!
  HTTP server running on http://${hostname}:${port}
  GraphQL WebSocket server running on ws://${hostname}:${port}${graphqlEndpoint}
`)
})()

Running Next.js

Now that we have the custom server implemented, you start it by running:

node server.js

You can also check a full example on our GitHub repository here (opens in a new tab)