GraphQL::PersistedQueries Build Status

GraphQL::PersistedQueries is the implementation of persisted queries for graphql-ruby. With this plugin your backend will cache all the queries, while frontend will send the full query only when it's not found at the backend storage.

  • 🗑Heavy query parameter will be omitted in most of cases – network requests will become less heavy
  • 🤝Clients share cached queries – it's enough to miss cache only once for each unique query
  • 🎅Works for clients without persisted query support

Sponsored by Evil Martians

Getting started

First of all, install and configure apollo-link-persisted-queries on the front–end side:

import { createPersistedQueryLink } from "apollo-link-persisted-queries";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";


// use this with Apollo Client
const link = createPersistedQueryLink().concat(createHttpLink({ uri: "/graphql" }));
const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: link,
});

Add the gem to your Gemfile gem 'graphql-persisted_queries' and add the plugin to your schema class:

class GraphqlSchema < GraphQL::Schema
  use GraphQL::PersistedQueries
end

Heads up! If you've already switched to interpreter mode and and AST analyzers—make sure AST plugin is added before GraphQL::PersistedQueries:

class GraphqlSchema < GraphQL::Schema
  use GraphQL::Execution::Interpreter
  use GraphQL::Analysis::AST
  use GraphQL::PersistedQueries
end

Pass :extensions argument as part of a context to all calls of GraphqlSchema#execute, usually it happens in GraphqlController, GraphqlChannel and tests:

GraphqlSchema.execute(
  params[:query],
  variables: ensure_hash(params[:variables]),
  context: {
    extensions: ensure_hash(params[:extensions])
  },
  operation_name: params[:operationName]
)

You're all set!

Advanced usage

All the queries are stored in memory by default, but you can easily switch to another storage (e.g., redis:

class GraphqlSchema < GraphQL::Schema
  use GraphQL::PersistedQueries, store: :redis, redis_client: { redis_url: ENV["MY_REDIS_URL"] }
end

We currently support memory, redis, redis_with_local_cache and memcached out of the box. The detailed documentation can be found here.

When the error occurs, the gem tries to not interrupt the regular flow of the app (e.g., when something is wrong with the storage, it will just answer that persisted query is not found). You can add a custom error handler and try to fix the problem or just log it.

Since our queries are slim now, we can switch back to HTTP GET, you can find a guide here.

batch-link allows to group queries on the client side into a single HTTP request before sending to the server. In this case you need to use GraphqlSchema.multiplex(queries) instead of #execute. The gem supports it too, no action required!

apollo-link-persisted-queries uses SHA256 for building hashes by default. Check out this guide if you want to override this behavior.

An experimental tracing feature can be enabled by setting tracing: true when configuring the plugin. Read more about this feature in the Tracing guide.

📖 Read more about the gem internals: Persisted queries in GraphQL: Slim down Apollo requests to your Ruby application

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/DmitryTsepelev/graphql-ruby-persisted_queries.

License

The gem is available as open source under the terms of the MIT License.