Urql: Persisted queries

Created on 20 Feb 2019  路  10Comments  路  Source: FormidableLabs/urql

Relay and Apollo support a concept called "persisted queries" whereby the GraphQL queries are persisted on the server side, and the client only needs to send an identifier (eg. a hash) to execute it. This avoids having to re-upload and re-parse the query every time it's executed, and the server can store the query in some intermediate form (such as a serialized AST) to improve performance.

Does urql support sending query IDs rather than the entire query? How would I integrate persisted queries into urql? I guess it'd need a Babel transform of some sort?

Reference: https://facebook.github.io/relay/docs/en/persisted-queries.html

Even better would be support for Apollo's "automatic persisted queries" (see https://blog.apollographql.com/automatic-persisted-queries-and-cdn-caching-with-apollo-server-2-0-bf42b3a313de)

help wanted 鉀忥笍

Most helpful comment

So I did get it working 馃槂

I just need to clean up the code a bit, as it's a bit messy at the moment. I'll post it to a new repo soon 馃槃

It also seems like any hash might work

You'd think that based on the docs, but actually if you use Apollo Server and try to persist a query, and send a hash that doesn't match the SHA256 of the query, it throws an error:

provided sha does not match query

Seems like it's hardcoded to use SHA256:

https://github.com/apollographql/apollo-server/blob/2d1544d049429f979cfcb28c9b83589e23873885/packages/apollo-server-core/src/requestPipeline.ts#L167-L172

https://github.com/apollographql/apollo-server/blob/2d1544d049429f979cfcb28c9b83589e23873885/packages/apollo-server-core/src/requestPipeline.ts#L68-L72

I imagine other implementations are similar (I'll have to see if there's a PHP implementation, as I'll be using this with a PHP server).

The Web Crypto API supports SHA256, so at least I don't need to load a JS library for SHA256 (in modern browsers at least).

All 10 comments

It does not, currently, but this can probably be achieved by writing an alternative fetchExchange. :) one of the ideas of urql is that it's super customisable. We can't provide all features out of the box but if anyone is willing to create a package for persisted queries let us know and we'll help out 馃憣

So I've been thinking about this a bit... It seems like Apollo's "automatic persisted queries" would be a good relatively simple implementation. The protocol is documented here: https://github.com/apollographql/apollo-link-persisted-queries#protocol. Basically, you first try the query by just sending a SHA256 hash of the query. If the server already has the query text cached, it runs the query like normal. Otherwise, it returns a PersistedQueryNotFound error, at which point you need to send the full query text.

At a high level, I think you're right and this could use a modified version of the fetch exchange that first sends the query with just the hash, and if that fails, sends the entire query.

It seems like a lot of the existing fetch exchange (eg. the AbortController handling, most of the fetchOptions, etc) would be reusable. Should I pull the reusable stuff out into a separate module that both the current fetch exchange and this new hypothetical "persisted query fetch exchange" use? Or should I instead make the existing fetch exchange more pluggable, and have the new "persisted query fetch exchange" reuse the core fetch exchange?

I'm working on this 馃槃 Do you think it'd be okay to live in this repo (and published as a separate package), or would you rather it be in a totally different repo?

@Daniel15 Awesome! I think for now it'd be great if it could live in a separate repository, but let me know if you need any help setting sth up or making that work 馃憤 (You can also DM me on Twitter @_philpl)

Ultimately we don't want all custom exchanges to live in the main repository or package; maybe at some point we'll convert to a mono repo, but for now this might be the better way to proceed.

You could also implement this as an exchange that sits in front of fetch potentially? But whatever you prefer 馃槄 I'm not sure which one is easier to write right now

It also seems like any hash might work; they do specify that SHA256 is their default but the urql exchange could default to a non-cryptographic hash which we already generate in our exchange pipeline

So I did get it working 馃槂

I just need to clean up the code a bit, as it's a bit messy at the moment. I'll post it to a new repo soon 馃槃

It also seems like any hash might work

You'd think that based on the docs, but actually if you use Apollo Server and try to persist a query, and send a hash that doesn't match the SHA256 of the query, it throws an error:

provided sha does not match query

Seems like it's hardcoded to use SHA256:

https://github.com/apollographql/apollo-server/blob/2d1544d049429f979cfcb28c9b83589e23873885/packages/apollo-server-core/src/requestPipeline.ts#L167-L172

https://github.com/apollographql/apollo-server/blob/2d1544d049429f979cfcb28c9b83589e23873885/packages/apollo-server-core/src/requestPipeline.ts#L68-L72

I imagine other implementations are similar (I'll have to see if there's a PHP implementation, as I'll be using this with a PHP server).

The Web Crypto API supports SHA256, so at least I don't need to load a JS library for SHA256 (in modern browsers at least).

@Daniel15 Awesome! It'd be pretty cool to have an urql-exchange-persisted-queries or something! Excited for this issue to make some progress :tada:

It's a bit surprising given that their docs were a little unclear on this. I assumed it would accept any hash and associate it with a query on a cache-miss. Oh well

I need to add a few more unit tests, but I published an initial version here: https://github.com/Daniel15/urql-persisted-queries. Let me know if you have any feedback :)

@kitten - Actually is there somewhere in the docs I should link it from? Is there an index for "custom exchanges" at the moment?

@Daniel15 Hiya, sorry for the late reply!
Your exchange has already been added here: https://github.com/FormidableLabs/urql/blob/master/docs/exchanges.md

We'll try to integrate this into the next website upgrade as well and add more links to this document in the future.

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tgrecojs picture tgrecojs  路  4Comments

alexraginskiy picture alexraginskiy  路  3Comments

danielres picture danielres  路  3Comments

wodnjs6512 picture wodnjs6512  路  3Comments

Andrew-Talley picture Andrew-Talley  路  4Comments