Apollo and Koa integrations for persisted GraphQL queries.
$ yarn add @shopify/graphql-persisted
This package includes two parts, both of which must be used together in order to make persisted GraphQL queries:
- An Apollo link that knows how to add persisted document IDs to an operation, and interpret server responses indicating that a persisted query was not found
- A Koa middleware that knows how to extract a persisted document ID and fetch the full document body
@shopify/graphql-persisted/apollo entrypoint exports a
createPersistedLink function. This function returns an Apollo link which should be added before the HTTP link:
This function accepts an optional
options object. The following option is available:
idFromOperation?(operation: Operation): string | undefined | null: calculates the unique ID to use for the persisted query, which will eventually be passed to the server’s
cache#getmethod to retrieve the full query body. If omitted, this option will default to pulling the
idfield off of the
DocumentNode, which works well in combination with documents compiled using
graphql-mini-transforms(used by default in sewing-kit).
The behavior of this link when a persisted query is not found for a particular ID depends on the
cacheMissBehavior passed to your server middleware, which is documented below.
The Koa middleware from this package will parse the request body, extract the ID, and attempt to resolve it to a full document body, replacing the request body’s
query field if a match is found. You can construct this middleware with the following options:
cache: A cache object with a
setmethod (both of which can be asynchronous). You can use this option to store and retrieve persisted documents from a dedicated store like Redis.
cacheMissBehavior: A member of the exported
CacheMissBehaviorenum. This dictates how the system will handle cases where a full document body could not be retrieved for an ID. The default is
;;;;// We'll use koa-redis since we probably use redis for sessions,// too. You can use any store you want, though.;app.usecreatePersistedGraphQLMiddleware,;// additional code, including whatever middleware will actually// handle the GraphQL query
When the middleware attempts to resolve an ID to a query document, it attempts to do the following:
ctx.state.assets.graphQLSourceexists, call it and wait on the result. If a result is found and a cache option was provided when creating the middleware, return the result and save it to the cache using
cache.set. This step makes it automatic to get persisted queries going for apps using sewing-kit and
- If a cache is present, call
cache.getwith the ID and wait on the result.
If no value was found during this process, the GraphQL call will fail in a way determined by the
CacheMissBehavior.SendAlways(default): the server will respond to the client with an error that tells it to always send the full query document for operations with that ID. It will never attempt to store those documents in the cache. The query that had this error will be immediately retried before calling the remaining Apollo links in the chain.
CacheMissBehavior.SendAndStore: the server will respond to the client with an error that tells it to send the full query document on an immediate retry. The server will then store that value in the cache against the ID. Subsequent calls will once again only send the ID.
CacheMissBehavior.Error: the server will respond to the client with an error, and no retry will be performed.
These options provide you full control over the behavior of clients sending persisted queries you do not recognize. If you use sewing-kit and want to get persisted queries only for the "current" set of queries, but want to allow old queries to still work, use
SendAlways. If you want to maximize the performance benefit of persisted queries, use
SendAndStore. Finally, if you want to prevent queries that have not already been persisted, use