GraphiQL

GraphiQL is an in-browser IDE for writing, validating, and testing GraphQL queries.

By default, GraphiQL is enabled only when in development and served under the /graphql route for GET requests with a accept: text/html header. You can configure or completely disable GraphiQL with the graphiql option.

Default Document String

You can set the default document string for GraphiQL by setting the defaultQuery option.

Set the default Document String
import { createServer } from 'node:http'
import { createYoga } from 'graphql-yoga'
 
// Provide your schema
const yoga = createYoga({
  graphiql: {
    defaultQuery: /* GraphQL */ `
      query {
        hello
      }
    `
  }
})
 
const server = createServer(yoga)
server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Disable GraphiQL

You can disable GraphiQL simply by setting graphiql: false.

💡

Be aware that disabling GraphiQL does not really make your GraphQL server more secure. As long as the introspection and/or the “did you mean x” suggestion feature of GraphQL are enabled.

You can further decrease your attack surface by disabling GraphQL introspection.

Learn more about disabling introspection

Disable GraphiQL
import { createServer } from 'node:http'
import { createYoga } from 'graphql-yoga'
 
// Provide your schema
const yoga = createYoga({ graphiql: false })
 
const server = createServer(yoga)
server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Dynamic Options per Request

You can also dynamically set GraphiQL options based on the incoming request. This allows rendering GraphiQL conditionally e.g. based on a header presence or value.

Dynamic options based on the incoming request
import { createServer } from 'node:http'
import { createYoga } from 'graphql-yoga'
 
// Provide your schema
const yoga = createYoga({
  graphiql(request) {
    if (request.headers.get('graphiql-enabled')) {
      return true
    }
    return false
  }
})
 
const server = createServer(yoga)
server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Within the function passed to graphiql you also have access to the serverContext. E.g. on Node.js it contains the http.Request and http.Response objects.

import { createServer } from 'node:http'
import { createYoga } from 'graphql-yoga'
 
// Provide your schema
const yoga = createYoga({
  graphiql(request, { req, res }) {
    // access something attached to the request object
    // e.g. a user object added by an auth middleware.
    if (req.user.role === 'admin') {
      return true
    }
    return false
  }
})
 
const server = createServer(yoga)
server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Offline Usage

By default, GraphiQL code is served from a CDN because if we added GraphiQL code inside Yoga, it would end up with huge bundle size and exceed the payload limit for some environments for example (CF Workers, AWS etc). If you want to use GraphiQL from a local version, you need to install it manually.

npm i @graphql-yoga/render-graphiql

And you need to pass imported renderGraphiQL to createYoga like below:

Render GraphiQL offline
import { createYoga } from 'graphql-yoga'
import { renderGraphiQL } from '@graphql-yoga/render-graphiql'
 
const yoga = createYoga({ renderGraphiQL })

Usage with Content Security Policy

In production, chances are you have enabled Content Security Policy (CSP) to prevent attacks.

Yoga by itself doesn’t require any special CSP configuration, but if you plan to use GraphiQL, you will need to add some sources to your CSP configuration:

  • script-src:
    • unpkg.com: used to load the graphql module.
    • unsafe-inline: GraphiQL is bundled with Webpack which rely on script tag injections.
  • style-src:
    • unpkg.com: GraphiQL styles are loaded directly from its module bundle, next to its scripts.
  • img-src:
    • raw.githubusercontent.com: The Guild logo is loaded from github