Persisted Queries
The relay compiler supports persisted queries. This is useful because:
the client operation text becomes just an md5 hash which is usually shorter than the real query string. This saves upload bytes from the client to the server.
the server can now whitelist queries which improves security by restricting the operations that can be executed by a client.
#
Usage on the client--persist-output
flag#
The In your npm
script in package.json
, run the relay compiler using the --persist-output
flag:
The --persist-ouput
flag does 2 things:
It converts all query and mutation operation texts to md5 hashes.
For example without
--persist-output
, a generatedConcreteRequest
might look like below:With
--persist-output <path>
this becomes:It generates a JSON file at the
<path>
you specify containing a mapping from query ids to the corresponding operation texts.
The example above writes the complete query map file to ./src/queryMaps/queryMap.json
. You need to ensure all the directories
leading to the queryMap.json
file exist.
#
Network layer changesYou'll need to modify your network layer fetch implementation to pass a doc_id parameter in the POST body instead of a query parameter:
#
Executing Persisted Queries on the ServerTo execute client requests that send persisted queries instead of query text, your server will need to be able
to lookup the query text corresponding to each id. Typically this will involve saving the output of the --persist-output <path>
JSON file to a database or some other storage mechanism, and retrieving the corresponding text for the ID specified by a client.
For universal applications where the client and server code are in one project, this is not an issue since you can place the query map file in a common location accessible to both the client and the server.
#
Compile time pushFor applications where the client and server projects are separate, one option is to have an additional npm run script to push the query map at compile time to a location accessible by your server:
Some possibilities of what you can do in ./pushQueries.js
:
git push
to your server reposave the query maps to a database
#
Run time pushA second more complex option is to push your query maps to the server at runtime, without the server knowing the query ids at the start. The client optimistically sends a query id to the server, which does not have the query map. The server then in turn requests for the full query text from the client so it can cache the query map for subsequent requests. This is a more complex approach requiring the client and server to interact to exchange the query maps.
#
Simple server exampleOnce your server has access to the query map, you can perform the mapping. The solution varies depending on the server and database technologies you use, so we'll just cover the most common and basic example here.
If you use express-graphql
and have access to the query map file, you can import the --persist-output
JSON file directly and
perform the matching using the matchQueryMiddleware
from relay-compiler-plus.
--persist-output
and --watch
#
Using It is possible to continuously generate the query map files by using the --persist-output
and --watch
options simultaneously.
This only makes sense for universal applications i.e. if your client and server code are in a single project
and you run them both together on localhost during development. Furthermore, in order for the server to pick up changes
to the queryMap.json
, you'll need to have server side hot-reloading set up. The details on how to set this up
is out of the scope of this document.
Is this page useful?