Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisted queries #196

Closed
Daniel15 opened this issue Feb 20, 2019 · 10 comments
Closed

Persisted queries #196

Daniel15 opened this issue Feb 20, 2019 · 10 comments

Comments

@Daniel15
Copy link

@Daniel15 Daniel15 commented Feb 20, 2019

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)

@kitten
Copy link
Collaborator

@kitten kitten commented Feb 20, 2019

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 👌

@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Jun 3, 2019

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?

@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Jun 5, 2019

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?

@kitten
Copy link
Collaborator

@kitten kitten commented Jun 5, 2019

@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

@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Jun 7, 2019

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).

@kitten
Copy link
Collaborator

@kitten kitten commented Jun 7, 2019

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

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

@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Jun 9, 2019

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 :)

@Daniel15 Daniel15 closed this Jun 9, 2019
@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Jun 9, 2019

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

@Daniel15 Daniel15 reopened this Jun 9, 2019
@kitten
Copy link
Collaborator

@kitten kitten commented Aug 1, 2019

@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.

@kitten kitten closed this Aug 1, 2019
@Daniel15
Copy link
Author

@Daniel15 Daniel15 commented Aug 2, 2019

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

2 participants