Building Ember Apps with GraphQL
Luckily, at work I was able to experiment with the integration of Ember with GraphQL and I have a few takeaways to share. Luckily, if you’re the type of person that likes to watch and listen my friend Rocky and I did a conference talk on the subject at EmberFest 2018. For this talk I also prepared an Ember sample repo showing how to integrate a few different clients, test techniques and GraphQL goodies within an Ember project.
What is GraphQL?
This topic has been covered by the GraphQL website rather well but to sum it up it’s a replacement for how you request data from a server, it’s typed, and it’s a query language so your request is infinitely dynamic(-ish) in what you can ask for.
Why is GraphQL popular?
There’s so many new ideas and it’s important to at least to try to understand the appeal. It could be the re-packaging of an existing idea, marketing, or something that truly redefines the approach to the problem. In my opinion GraphQL’s popularity is justified in effort that is put into standardizing the query language and providing the tooling to make implementation a relative breeze. It’s not easy to replace something as spec’d as HTTP and REST.
I think GraphQL is also really popular because of types and introspection (you always know what you’re working with and what you get), it’s adaptive (add fields to a type as you go), and requests mimic the response so you only get what you’ve asked for (it so closely looks like an extension of JSON that the language itself feels very natural).
Lastly, I think part of the appeal to GraphQL is due to the fact that it’s strict in the right places. All of your queries in GraphQL are a POST to the same endpoint. This means that you don’t need to worry about http codes and URL structures. Most API’s evolve organically and in many companies there isn’t the foresight to make a totally RESTful API that utilizes the breadth of what is defined in the “proper way”. Most of the API’s I’ve used don’t match this unicorn of the perfect RESTful API. GraphQL isn’t strict in the URL structure (there’s only one endpoint), it isn’t strict about how you ask for something (relationships and the conditions you ask for something aren’t strict). GraphQL is strict in defining what operations are available, and what you can expect.
To sum it up, GraphQL feels like a more natural extension of what we as developers are looking for.
Ember with GraphQL
So let’s get to the meat and potatoes of Ember and GraphQL. GraphQL is just a way of requesting data and there are a few options.
In terms of the Ember ecosystem the most opinionated integration is ember-apollo-client. If you are interested in using the Apollo client for GraphQL this is the way to go. The Apollo client is great because it abstracts things like request caching and middleware away in a way that you can rely on a community effort. One downside is that any changes that happen with Apollo upstream have to be integrated and managed in an Ember Way™️ through this client and the community.
Lightweight 3rd party clients
There are a number of clients that are lightweight and easy to integrate thanks to ember-<a href="https://github.com/ef4/ember-auto-import">auto-import</a>. A few of the popular ones I’ve tried are Lokka and graphql-request. You can import them directly but if your API is protected you’ll probably want to wrap them in a service so that you’re always supplied a fresh client with the current access token. These are very simple and offer fewer features, but are easier to integrate and probably require less effort upfront. Because your queries don’t change you can always move from one of these clients to Apollo down the road.
Ember Data and the Elephant in the Room
Ember Data is so closely matched to a JSON API spec, and adapters that somewhat match a resource on URL structure ala REST, that the mapping of Ember Data on to GraphQL is much more difficult. The closest implementation is ember-graphql-adapter which works best if you are also using the GraphQL ruby gem as mentioned in the docs. Any exceptions don’t map nicely, and behind the scenes it’s doing a custom parse and compilation step of GraphQL without using some of the great tooling to map queries and types through a digestable AST. I think due to the fact that resources are “typed” and the properties are defined that a mapper could exist that is more flexible and makes these easier but it also kind of breaks the paradigm of free-form querying.
The other difficult part with using GraphQL within Ember apps is the acceptance testing. Ember has a really wonderful extension of the application that makes testing so close to end-to-end testing with something like Selenium or Puppeteer, but without the cost. In order to handle this though there is often a need to “stub” the network layer.
With GraphQL all requests are a POST to the same endpoint. This means that stubbing requires understanding the payload itself and its embedded query. You aren’t able to rely on just check the http method and stub the resource endpoint.
I think the easiest way to do this right now within Ember is to use graphql-tools to understand the queries and variables, and something like pretender.js to intercept the network requests themselves, or to use PollyJS.
Using graphql-tools gives you total control, you could even map the handlers to an in-memory database so that mutations actually persist across tests.
PollyJS is a library from Netflix that will record all requests and responses between your frontend and the backend, so that the next time the request is made it can just dig up the recorded response (saved to disk and comitted) and replay it. It’s very similar to the VCR ruby gem. It’s not specific to GraphQL either, I think it’s really a fantastic tool and something that fits something like the complexity of GraphQL very well. The only downside is that your test cases have to exist within a real API, otherwise you’re left to modify the request/response (thanks to PollyJS’s great hook system) to meet your use-case, or just use graphql-tools as mentioned above.
In terms of tooling I want recommend using graphq-cli, along with a matching .graphqlconfig. It’s becoming more or less a standard and it will make fetching your GraphQL schema easier. Even better this configuration can hook into a graphql eslint plugin that will make sure that all your queries are validated against a valid schema and checked during your ember tests.
Give it a try
If this sounds interesting I would recommend giving it a try. I think there is enough maturity in the ecosystem, both with Ember and GraphQL, that it can be done. If you have any questions reach out to me on twitter @chadian, also check out my Ember sample app that has some documented examples with different clients and testing techniques.