Hacker News new | comments | ask | show | jobs | submit login
Introduction and Quick Guide to GraphQL for BackEnd and FrontEnd (time2hack.com)
112 points by patelpankaj 11 months ago | hide | past | web | favorite | 37 comments

I’m confused about the sell of Graphql as being a more “flexible” API. From the client side it seems great. You basically define what data you want in your query, hit 1 endpoint and get said data. If you your data needs change, simply change your query. Or so says most every Graphql blog post out there, handwaving over how a backend would actually handle that.

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.

I've been using GraphQL for a bout a year now on several projects. the 'flexible' part for me comes in more advanced scenarios like:

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.

Cool, thanks for your reply and insight. That does sound pretty useful!

You're hitting the nail on the head that implementing the resolvers is the hard part when building a GraphQL server! I work at Graphcool (www.graph.cool) and we recently open-sourced a new tool called Prisma that will help you with exactly that part! Our goal with Prisma is to automatically turn any database into a GraphQL API - right now we have connector for MySQL, but we're working on more for Postgres, MongoDB, Neo4j etc... You're then building your application server using GraphQL bindings (read more here: https://blog.graph.cool/reusing-composing-graphql-apis-with-...) which allows to simply delegate incoming queries to the underlying Prisma engine.

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

Nice! After I wrote that comment my brain gears got turning and I started wondering how I might build something exactly like that.

The client only gets back the fields requested. Graphql resolvers are tricky but you would have had to coalesce that data somehow, such as on the client. Graphql just provides more structure. It allowed me to replace ad hoc query parameters, coalesce on server instead of client, and no longer need to version my API.

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

The return fields specify the data you want on creation of resource. In REST, the server used to return either full data or the [201](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201)

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

> In REST, the server used to return either full data or the [201](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201)

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

translate from REST to SQL is exactly what PostgREST is doing and you get the same flexibility as with graphql

I guess we're approaching a sort of Atwood's law for GraphQL. Here's the GraphQL version of PostgREST: https://github.com/postgraphql/postgraphql

Postgraphile is very nice because you only need a PostgreSQL and a front-end app with Postgraphile in between. No need to write tiedous middleware functions. And it watches your DB schema and automatically generates a documentation for GraphIQL. Nice piece of software !

This is a great and very instructive post for people who are new to GraphQL!

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

I do NOT want to sound like I hate graphQL. I don't know enough to do that even if did want that.

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?

REST & GraphQL are ways to structure the interface of your API. Http is a transport. You can implement REST or graphQL over http.

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.

These guides always ignore authentication/authorization. Is there a standard pattern or way to do these when using GraphQL?

Edit: a quick search for apollo graphql auth turns this up for reading https://www.apollographql.com/docs/react/recipes/authenticat...

I ran into the issue of authentication when trying to learn GraphQL. I made a Node/GraphQL/React boilerplate with an example implementation of authentication in place. It's my first foray into both Node and GraphQL so I apologize for any inconsistencies.


This guide really only provides an overview of what GraphQL is so I think it's fair they don't go in depth about auth topics.

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

It's simple. In graphql one request matches many routes. That's why when one resolver crashes that field gets null in the response but other fields from other resolvers are still present. (This could cause issues in some apps that would in turn overwrite valid data with a null if the user hits save and the app did not account for null fields).

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

For authorization, from what I've seen you'll generally enforce permissions inside resolvers. You can propagate a capability from one field to it's children, which allows you to not have to look up permissions on children fields.

true, the context param in resolvers are the way to do so

I was actually thinking more about passing it as part of the root. For instance, if a person can see all their friends, then you could construct the root for the friend with something like "public only" permission to that person's info, which would prevent someone from accessing private info when checked properly inside the person type.

(Although you certainly can use context at the first resolver, it gets less useful the further down you go imo for authorization)

that also makes sense; and I guess it's just a matter of use-case and preference.

> These guides always ignore authentication

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.

I wrote about this last year, https://zach.codes/handling-auth-in-graphql-the-right-way/ it can be pretty easy to do, but nobody talks about it...

Write a parent function that all resolvers go through. you can then add checks if the resolver is public, or whatever you want

well it is a quick guide. auth is a separate topic. Best way to do it is I guess through context in resolvers

If you're still using GraphiQL I urge you to try out Insomnia, their GraphQL support is fantastic. The only thing I miss is auto-completion of all fields, having to type every attribute can be tedious. Also, if you need to pass headers to authenticate, Insomnia handles that gracefully, whereas with GraphiQL you need to basically install an extension (which you will then forget to disable and YouTube will act funny).


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

We've been working on a GraphQL IDE that sits on top of GraphiQL but provides many additional features: https://github.com/graphcool/graphql-playground

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

GraphiQL also has history FYI. On your demo tapping "tracing" seems to do nothing. On mobile safari

Have you checked out Insomnia's environments feature? It seems like what you're looking for. You can create an environment for production/staging/etc, define a variable in each one, use that variable in the header value, and switch between environments any time.

Also, Insomnia supports autocompletion of GraphQL query attributes. Maybe you have found a bug?


If anyone wants an awesome starter kit so you can start hacking GraphQL out of the box, I strongly recommend the Apollo Universal Starter Kit. [0] It's a very resent project with a lot of amazing developers getting behind it contributing code to several branches every day. The documentation is lacking but there are tons of amazing examples on how to solve most of the common web and native app features. If you are using Apollo for a project, they have recently removed the Redux dependency opting for Apollo Link State instead meaning that there isn't two different stores, only one.

[0] https://github.com/sysgears/apollo-universal-starter-kit

Perhaps it's nitpicking, but what benefit is it to not make the GraphQL language be valid JSON?

A JSON dsl would be significantly more verbose to support the feature set. GraphQL is super straightforward.

There is a json (technically object) to graphql converter up on npm I use to dynamically create queries. I use it sparingly due to verbosity https://github.com/kadirahq/graphqlify

valid point, but are you talking about the schema or the results. For Schema, it makes sense to have a different DSL as JSON's cons include the inability to describe types on values.

Just with 3 types (string, number, boolean), we can not cover more advanced types.

Just going to put this here: http://jsonapi.org/

Great stuff!

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

Couple of interesting ones -

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

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact