If you plan to use Relay to achieve the same goal, you should definitely check this post on the official GraphQL blog.
GraphQL is ultimately only a protocol, meaning there are dozens of projects for both client and server side implementations of it. Apollo, in the other hand, is a suite of open-source tools & products built by (very nice folks at) the Meteor Development Group.
Among these projects, there is graphql-tools, which facilitates the creation of a executable schema, and apollo-client, which presents itself as “The fully-featured, production ready caching GraphQL client for every server or UI framework”. Quite bold, huh?
We are going to need two schema building tools:
What we are saying here is that our schema has a single type called Query and that this is the root query type, meaning it’s fields are queryable at the top level of the schema — in this case, the
helloWorld field, which resolves to a string.
Then you define resolvers as a nested object that maps type and field names to resolver functions:
Finally, you combine the type definitions and the resolvers into an executable schema using
After we’ve managed to create an executable schema, we can resolve queries against it using the official graphql-js project as follows:
Done! We can resolve GraphQL. The code so far can be bundled using webpack or whatever tool you use to build your code to be executed in the browser, and it will work just fine.
I’ve created a repository to serve as code reference for this post. It’s available on GitHub, it has a ready to use building system and node server for you to try the code presented here. Checkout the tag 1-hello-world to see this check point.
Now that you have a way to resolve GraphQL queries in the browser, we can move forward and add a more advanced schema, with resolvers that map to REST requests.
To keep up with simplicity, I’ll use an online fake REST API called JSONPlaceholder. It has a rough blog schema, with posts, users, comments, etc, which is just perfect for our use case.
First of all, let’s update our schema to define these new types:
Now, we’ll update the resolver map as follows:
No we can query posts:
Checkpoint: checkout to tag 2-rest-resolvers on the code reference repo to try this out on your browser.
Ok, that’s pretty cool. What if we wanted to get a single post from the API, though? Well, easy enough. Here is how we could make a query for the post with id 1:
Now, having a look at our mocked API for posts, we can see that it returns yet a fourth property on each post object: the
userId. That's a good time for...
Relations in GraphQL are simply more resolvers, as I expect you already know. Follow up as we add the Post’s author field to the schema, as well as the User’s posts field, together with their resolvers:
Ok, things are becoming really interesting. Now we can make GraphQL work it’s magic, doing crazy stuff such as “grabbing the posts with the same author as post 1”:
Oooh, that’s truly amazing! I’ll just take break for a coffee and contemplate such good work we’ve accomplished so far…
Meanwhile, another checkpoint for you to run: 3-relationship-resolvers.
Mutations in GraphQL are just more field resolvers, only with some additional behavior. Having that said, to create
addPost mutation we will basically create a resolver that fetches using the HTTP method
POST as follows:
Our mutation queries then have to be identified as such:
Two more checkpoints and we’re done: 4-mutation-resolvers.
Ok, I know that running a static query stored in a variable in the index.js of our application isn’t going to be enough for long. The next step is integrating what we already have with Apollo Client (“The fully-featured, production ready caching GraphQL client for every server or UI framework”. Again: long description, not modest, but quite accurate).
To create an Apollo Client instance you must instantiate the ApolloClient class with a configuration object containing, at least, the network interface which the client will use to make GraphQL requests. Usually, in a front-end/back-end application this means using the included helper createNetworkInterface, which would basically send POST requests to a backend on the same domain of the running application. It looks pretty much like this:
And, to perform a query, something like this:
The code above would be just fine if we had a backend serving GraphQL — which we don’t. Good enough we’ve being building our own wrap around the REST API just earlier in this post.
What we now have to do is make ApolloClient use the GraphQL schema and resolver we built as were we doing before:
Ok, what the heck is going on here?
First, we are instantiating ApolloClient with a completely custom networkInterface. It consists of an object with the single required method query, which will be called by the client to resolve queries. This method will receive a single argument; an ApolloClient Request Interface.
Second, we use an available helper,
printAST, to process this request object back into a valid GraphQL query string (much similar to the ones we were statically using before).
Last but not least, we run the query against the schema as have we done before, providing it with the schema, the query, the initial root, a context (null here, for we don’t need it yet), the variables, and the operation name, in that exact arguments order. Most of the arguments are not mandatory, as we’ve seen this same function be executed with only the first two just a few words back in this post.
If you have any question about the query execution part, please have a look at GraphQL’s official documentation on query execution.
We can now use the client as we normally would:
Time for one final checkpoint: 5-apollo-client.
Originally published at taller.net.br.