GraphQL with Twig: Questions and answers
Whats wrong with Drupal’s approach?
Drupal, as most content management systems, follows the traditional layered approach. The incoming request is mapped to a controller which prepares the information to display and pushes it through a display layer. The controller may be extended by modifying the execution result (process, preprocess) and the display can be altered by template overrides.
There’s nothing wrong with that, since this pattern serves a very specific workflow:
- Install a module
- Features appear immediately
- Tweak it until everybody is happy
This works great, until a product development team is involved that is not willing to bend to what’s available out of the box. If the requirements and expectations are very specific, developers have to work against the process the framework dictates. Lot’s of preprocessing, altering and template overriding scatter responsibilities across multiple files, modules and themes. Just consider how many templates are in play when rendering a single views listing. Without constant compromising, this easily gets out of hand and maintainability is dropping with every new feature.
Opinion Alert: In believe that this is the unspoken reason for the whole fuzz around “decoupling Drupal”.
Decoupling puts the frontend in charge.
REST, JSONAPI and GraphQL act as interfaces that allow to the display layer to develop without being shackled to a backend implementation that has to follow step by step. But if Drupal becomes truly decoupled, we can achieve this goal with any display layer. Also with Twig running in the same PHP process, which - for a lot of smaller projects - is good enough.
How does it perform?
Thats the first question on every single occasion we talk about the GraphQL in Twig. And to clear out the first basic misunderstanding: There are no HTTP requests involved. When used with Twig, only the GraphQL processor is invoked to resolve a queries result.
Right now, this is not significantly slower than render arrays, since it basically does the same as you would do in a preprocessing step to get the data you want. And it natively integrates with Drupal’s existing render caching mechanisms, so the approach doesn’t bring regressions on this side.
But GraphQL itself brings a lot more potential for performance improvements. Since the structure of the query is known in advance we are able to optimise the tree of requirements on a higher level.
For example, nested entity relations (e.g. a list of articles that also requires information about the authors and related posts) are resolved more efficiently with deferred resolvers that are able to aggregate each level into one fetch statement. The approach is similar to lazy builders in the current theme layer, but applied automatically.
Aren’t we back at putting SQL queries in templates?
At our DrupalCon Nashville talk, one participant stated that he “would like to try it out in a dark room, where nobody see’s him …”, which perfectly sums up the collective gut feeling. It seems like we are breaking a law that we’ve been fighting for the last 10 years, but that’s not true.
We could answer this with another question:
Why is GraphQL allowed in React components, but not in Twig templates?
But thats too easy, so we’ll dig a little deeper. The GraphQL fragments in template files are requirement definitions, but don't contain any rules on how to resolve them. The implementation of GraphQL fields in the background have to adhere the interface definition, but the implementation is fully replaceable.
The annotations are collected during the Twig compile step and assembled to one query per root template. At render time, this single query is executed and the result is passed down the template tree. This means, the fragment in a
node--teaser.html.twig is not executed 20 times in a listing of 20 articles, like the infamous SQL template hacks that brought us to Twig in the first place.
That being said, you still can do dumb stuff with too deeply nested queries. But thanks to query complexity analysis it’s possible to catch bad ideas automatically and let the frontend developers work on a fixed performance budget. And since we have full control over the schema and are able to remove fields at will, we can keep a tight grip on what the frontend can do and what not.
We hope this cleared up some questions, but most likely there are more. Luckily, we are going to host a webinar on this topic on May 11th 2018. You will get a walk through using GraphQL with Drupal and a chance to join the discussion. See you there!