Plugins
Yoga builds upon the GraphQL plugin system envelop and adds additional HTTP specific hooks for customizing both the GraphQL execution and HTTP layer. Many of the additional features of Yoga are added via plugins. If you need to customize your GraphQL API you can also write your own plugins.
Using Plugins
You can both use Yoga or Envelop plugins with GraphQL Yoga.
When there is both a Envelop and Yoga specific plugin available, you should always opt-in for the Yoga variant as this one allows certain optimizations compared to just an Envelop plugin. As envelop plugins have only control over the GraphQL execution for example a plugin such as the response-cache, can never act on the HTTP level. However, the yoga response-cache, Persisted Operations or Defer/Stream plugin utilizes the HTTP level hooks, and thus can completly skip all of the expensive GraphQL execution steps for serving cached results.
Yoga Plugin Example
Please refer to the corresponding feature documentation pages. E.g. Response Cache, Persisted Operations or Defer/Stream.
import { createServer } from 'node:http'
import { createYoga } from 'graphql-yoga'
import { useDeferStream } from '@graphql-yoga/plugin-defer-stream'
const yoga = createYoga({
plugins: [useDeferStream()]
})
const server = createServer(yoga)
server.listen(4000, () => {
console.info('Server is running on http://localhost:4000/graphql')
})
Envelop Plugin Example
Envelop is a lightweight JavaScript (TypeScript) library for customizing the GraphQL execution layer, allowing developers to build, share and compose plugins that enhance the capabilities of your GraphQL server. GraphQL Yoga uses Envelop under the hood so you can easily extend your server’s capabilities with the plugins from Envelop Ecosystem
The following example adds GraphQL JIT to our GraphQL Server using Envelop GraphQL JIT Plugin
import { createSchema, createYoga } from 'graphql-yoga'
import { useGraphQlJit } from '@envelop/graphql-jit'
// Provide your schema
const yoga = createYoga({
schema: createSchema({
typeDefs: /* GraphQL */ `
type Query {
greetings: String!
}
`,
resolvers: {
Query: {
greetings: () => 'Hello World!'
}
}
}),
plugins: [useGraphQlJit()]
})
// Start the server and explore http://localhost:4000/graphql
const server = createServer(yoga)
server.listen(4000, () => {
console.info('Server is running on http://localhost:4000/graphql')
})
Writing Plugins
Sometimes you might want to build your own plugins. You can write your own Yoga plugin and even
share it with other people by publishing it to npm
.
A good entry-point for discovering how to write Yoga plugins is to look at the source code of the existing plugins maintained by us.
The most hooks for Yoga origin from the envelop plugin system. Please refer to the Envelop Plugin Lifecycle documentation for more information. In addition, Yoga adds more HTTP specific hooks.
Plugin Lifecycle
The following diagram shows the plugin lifecycle of GraphQL Yoga. For a detailed description of each hook, please refer to the detail sections of each hook.
onRequest
This hook is invoked for ANY incoming HTTP request. Here you can manipulate the request or create a short circuit before Yoga handles the request.
Exceptions thrown by this hook are not caught. This means they will buble up to the HTTP server underlying implementation.
For example, the node:http
server crashes the entire process on uncaught exceptions.
Prefer onRequestParse
when possible, or wrap the hook code in a try
block.
Example actions in this hook:
- Manipulate the request
- Short circuit before Yoga handles the request
API
request
: The incoming HTTP request as WHATWGRequest
object. Learn more about the request.serverContext
: The early context object that is shared between all hooks and the GraphQL execution. Learn more about the context.fetchAPI
: WHATWG Fetch API implementation. Learn more about the fetch API.url
: WHATWG URL object of the incoming request. Learn more about the URL object.endResponse
: A function that allows you to end the request early and send a response to the client.
Example
import { Plugin } from 'graphql-yoga'
function useAuth(): Plugin {
return {
onRequest({ request, fetchAPI, endResponse }) {
if (!request.headers.get('authorization')) {
endResponse(
new fetchAPI.Response(null, {
status: 401,
headers: {
'Content-Type': 'application/json'
}
})
)
}
}
}
}
onRequestParse
This hook is invoked for any incoming GraphQL HTTP request and is invoked before attempting to parse the GraphQL parameters. Here you can manipulate the request, set a custom request parser or apply security measures such as checking for access tokens etc.
Example actions in this hook:
- Manipulate the request
- Set custom GraphQL request parser (use custom GraphQL protocol)
- Apply security measures
onParams
This hook is invoked for an incoming GraphQL request after the GraphQL parameters (query
,
variables
, extensions
and operationName
) have been ATTEMPTED to be parsed.
Within this hook you can manipulate and customize the parameters or even implement a whole new way of parsing the parameters (if you wish to diverge from the GraphQL over HTTP specification).
In addition to that you could also short-circuit and skip the GraphQL execution. E.g. you might want to serve a result from the cache instead.
Example actions in this hook:
- Response Cache: Short-circuit GraphQL execution if response can be served from the cache.
- Persisted Operations: Load the
query
document string from the persisted operations store before running the execution. - APQ: Load/persist the
query
document string on the persisted operations store.
onParse
Called for parsing the GraphQL document. This hook has a before and after stage. You can hook into before the document is parsed and/or into after the document is parsed.
Example actions in this hook:
- Replace GraphQL parser and support future GraphQL syntax
- Collect metrics about parsing success/failures
onValidate
Called for validating the GraphQL document. This hook has a before and after stage. You can hook into before the document is parsed and/or into after the document is parsed.
Example actions in this hook:
- Register additional validation rules (e.g. Disable Introspection)
- Collect metrics about validation success/failures
onContextBuilding
Called for building the GraphQL context. This hook has a before and after stage. You can hook into before and after the context is built.
Example actions in this hook:
- Authentication
- Add data to context object (e.g. user data or dataloader instances)
onExecute
Called for executing a GraphQL mutation or query operation. This hook has a before and after stage. You can hook into before and after the GraphQL request is executed.
Example actions in this hook:
- Collect metrics about execution time
- Error logging/reporting
onSubscribe
Called for subscribing to a GraphQL subscription operation. This hook has a before and after stage. You can hook into before and after the GraphQL subscription is executed.
Example actions in this hook:
- Collect metrics about execution time
- Error logging/reporting
onExecutionResult
This hook is invoked for each result produced for GraphQL operation, before it is processed to be sent to client.
In particular, it is useful to handle batched operations. If a request contains batched operations,
this hook is called once of each operation, while onResultProcess
will be only called once for the
entire request.
Here, you can modify the result, to add monitoring or instrumentation extensions for example.
Example actions in this hook:
- Add metadata to results
- Collect errors
onResultProcess
This hook is invoked after a GraphQL request has been processed and before the response is forwarded to the client. Here you can customize what transport/response processor format should be used for sending the result over the wire.
Example actions in this hook:
- Specify custom response format
- Logging/Metrics
onResponse
This hook is invoked after a HTTP request (both GraphQL and NON GraphQL) has been processed and after the response has been forwarded to the client. Here you can perform any cleanup or logging operations, or you can manipulate the outgoing response object.
Exceptions thrown by this hook are not caught. This means they will buble up to the HTTP server underlying implementation.
For example, the node:http
server crashes the entire process on uncaught exceptions.
Prefer onRequestParse
when possible, or wrap the hook code in a try
block.
Example actions in this hook:
- Specify custom response format
- Logging/Metrics
API
request
: The incoming HTTP request as WHATWGRequest
object. Learn more about the request.serverContext
: The final context object that is shared between all hooks and the GraphQL execution. Learn more about the context.response
: The outgoing HTTP response as WHATWGResponse
object. Learn more about the response interface.
Example
import { Plugin } from 'graphql-yoga'
function useYogaSignature(): Plugin {
return {
onResponse({ request, response }) {
response.headers.set('X-GraphQL-Server', 'Yoga')
}
}
}