Introduction and Quick Guide to GraphQL for BackEnd and FrontEnd
time2hack.com
time2hack.com
But the reality, it seems, is not that. Now that we’re (finally) getting some posts digging into the backend implementations it’s not clear how the above can be true. AFAICT, the example in the Post is no different than a GET /users (or any other rpc type api). In fact, forcing the client to specify the return fields is completely unnecessary because unless I am missing something, the client is getting all the User fields back every time anyway?
I dunno. Maybe I’m missing something. Just seems like implementing a backend to be as flexible as we’re being sold would effectively be writing a schema-aware transpiler from Graphql to your underlying datastore’s query language.
Once I establish a relationship between two entities (`Types`), I can fetch an arbitrary combination of them from my endpoint. e.g., the resolvers that allow me to execute a query like 'fetch all posts by users who signed up since last week' to the same endpoint' can also answer 'fetch the Id of the authors of posts that start with the letter "a",' or even "fetch me every post by an author who's published a post in the past week titled with a word that starts with "C"'. All of these are possible just by defining the relationship b/t `Post` and `User`.
The other part I find really something is custom field-level resolvers. Instead of every field corresponding to a database table, the `GraphQL` server can execute arbitrary code to resolve a field. In the `User` / `Post` example, I can add a field called `weather` to `Post`. Whenever the endpoint is returning a `Post` with `weather` included in the response, it could fire an API call to a weather API for the weather at the time / location that post was created. To the API consumer, this is totally transparent and `weather` is returned as though it was already in the database.
This sort of arbitrary composition of data types is really at its best with `schema-stitching`. I have a bunch of content in a GraphQL-powered CMS BaaS, and using a few lines of code with `graphql-yoga` (a server), I can combine the CMS schema with a schema for my own custom data model, and even merge the two. e.g., extend my `Post` type in my CMS with a `weather` field from above.
Would be curios to hear your opinion on Prisma!
You can try it out here: https://www.prismagraphql.com/docs/quickstart/
You can also check out the 4min demo-video (with TypeScript) I made that explains how it works: https://www.youtube.com/watch?v=20zGexpEitc
If all your app does is fetch one user with two fields like this example it's hard to see the benefit. When you have sprawling backends with a large entity graph it is immensely valuable
Specifying the fields on mutation means data is inserted/updated and the query on the new data has following changes, and you can select form those changes
Nothing in the dissertation or any other describing document enforces or even suggests you have to do this, and in fact a popular standard gives a means for not doing this: http://jsonapi.org/format/#fetching-sparse-fieldsets
If you want to dive deeper and get some practical experience, I can recommend the following resources (disclaimer: I've personally contributed to all them):
- Fullstack tutorial with React & Apollo: https://www.howtographql.com/react-apollo/0-introduction/
- Backend tutorial for Node.js: https://www.howtographql.com/graphql-js/0-introduction/
- GraphQL Boilerplates (Node, TypeScript, React, Vue,...): https://github.com/graphql-boilerplates
But I'm not getting it. Graphql let's you say what data you want, at the cost of all network caching (everything is POST), browser caching (for those of us that work in web), and urls that make clear their general purpose (which sounds trivial, but if you are talking to multiple services/actions being able to see which call to look into the details of ends up to a lot of time savings).
Much magic is promised by the resolved, but as another commenter mentioned I see more handwaving than implementations. I'm sure examples exist, but I'm far less sure those examples are transferable.
Getting extra data in a request is NOT a big pain point for me, even on mobile (assuming the service is at all sane, and since implementing graphql well seems to be as much or less effort for the service developoer than meeting the level of "sane" that seems a safe assumption.) Do I get wasted data and bandwidth? Yes. Is fixing that worth losing the aforementioned benefits? I don't see how.
The graphql docs I've read say to implement caching on the client side...but that seems a dodge. Caching on the client is not the same as network caching, and is just as available on non graphql options. For browsers in particular it is an issue...caching relies heavily on GET requests, and while you can write your own caching on top in your application, that is defeating the bandwidth reduction benefit as well as introducing plenty of room for error - cache expiration is notoriously a very hard problems.
I recently did some PWA work and discovered: 1. Caching GET requests with the cacheAPI was trivial, though expiration was left to the dev. 2. Caching POST requests required you to roll your own solution. 3. The service worker could not access or copy the response object for anything involving CORS. You could tell the cacheAPI to cache a get response without examining the response, but you had no option to do so for POST, nor could you roll your own.
It is certainly possible I missed something...documentation of both the CacheAPI and CORS is shallow enough that I had to learn through experimentation and repeatedly reading parts of the specs.
TL;DR How are the benefits of GraphQl worth the sacrifice of network and browser caching?
GraphQL is a language not an implementation. Nowhere does it even say graphQL must use http, let alone POST. You can send a graphQL query with a GET request & cache it just fine.
In addition, graphQL's introspection system makes it super easy to write clients that do complex cache manipulation, like optimistic updates & a variety of cache invalidation / refetching patterns.
Edit: a quick search for apollo graphql auth turns this up for reading https://www.apollographql.com/docs/react/recipes/authenticat...
https://github.com/johnernaut/express-graphql-react-boilerpl...
If you're curios how authorization can be implemented in a GraphQL server, I recommend the following tutorial: https://www.prismagraphql.com/docs/tutorials/graphql-server-...
Also check out these two awesome projects that provide ways for implementing authorization with GraphQL:
- https://github.com/a-type/prisma-authorized
- https://github.com/maticzav/graphql-shield
If you want to see a practical example of how authorization can be implemented, check out this example project: https://github.com/graphcool/prisma/tree/master/examples/per...
So for authorization your API simply returns the fields allowed but not the ones disallowed. Auth itself is also covered in the official docs for graphQL and express graphql. You can just put your passportJS user in the context as well as the express request object. Pretty straightforward. Hardest part is retrofitting clients to handle sometimes null fields since graphQL still gives a 200 status code. Clients need to be modified to check for graphQL errors object instead of relying on status codes
(Although you certainly can use context at the first resolver, it gets less useful the further down you go imo for authorization)
Can't you just use whatever transport-level auth you prefer? I'd assume most GQL queries are over HTTPS so you could use cookies, HTTP Basic, HTTP Digest, a custom HTTP Auth scheme, SSL certs, API keys (through Basic or headers), … the world's your oyster.
Depending on your requirements or constraints, the authorisation would be handled either once at the top-level or on a resolver-by-resolver basis.
Write a parent function that all resolvers go through. you can then add checks if the resolver is public, or whatever you want
Actually, another feature I miss in Insomnia would be query groups, mainly to change the access token in the header in one place for a specific environment.
edit: I just realised it's OSS as well, so whiny people like me can potentially contribute features they're missing https://github.com/getinsomnia/insomnia
It has a more user-friendly documentation than GraphiQL as well as tabs and a history of previous operations. It also supports realtime GraphQL subscriptions and conforms to the industry-standard graphql-config format. Further, it allows to easily share your Playground and has support for query performance tracing :) Definitely check it out if you haven't seen it before
Also, Insomnia supports autocompletion of GraphQL query attributes. Maybe you have found a bug?
https://support.insomnia.rest/article/18-environment-variabl...
[0] https://github.com/sysgears/apollo-universal-starter-kit
Just with 3 types (string, number, boolean), we can not cover more advanced types.
For those interested I curate a bunch of dev/engineering related links everyday. I've curated about two dozen great links on graphql - https://www.discoverdev.io/tags/graphql
1. React, Relay and GraphQL: Under the Hood of The Times Website Redesign: https://open.nytimes.com/react-relay-and-graphql-under-the-h...
2. Build a Rotten Tomatoes Clone with GraphQL and Auth0: https://auth0.com/blog/build-a-rottentomatoes-clone-with-gra...
3. GraphQL vs. REST - A GraphQL Tutorial: https://www.toptal.com/api-development/graphql-vs-rest-tutor...