Don’t Push it: Using GraphQL in Twig
Traditionally Drupal defines data structures that provide a “standard” rendered output, which then can be adopted by the so-called “theme developer” to meet the clients' requirements. Template overrides, preprocess functions, Display Suite, Panels, Layouts - there are myriads of ways how to do this, and twice as many opinions determining the right one. When taking over a project the first thing is to figure out how it was approached and where the rendered information actually comes from. Templates only have variables that are populated during processing or preprocessing and altered in modules or themes, which makes it very hard to reason with the data flow, if you were not the person that conceived it in the first place.
There are ideas to improve the situation, but regarding the success of decoupling, perhaps it’s time to approach the problem from a different angle.
Push versus Pull
The current push model used by Drupal scatters responsibilities across modules, preprocess functions and templates. The controller calls the view builder to prepare a “renderable” that is altered 101 times and results in a set of variables that might or might not be required by the current theme’s template.
If we would turn this around and let the template define it’s data requirements (as it happens in decoupled projects naturally), we could achieve a much clearer data flow and increase readability and maintainability significantly.
And that’s what the GraphQL Twig module is supposed to do. It allows us to add GraphQL queries to any Twig template, which will be picked up during rendering and used to populate the template with data.
A simple example
This is already enough to pull the information we need and render it. Let’s have a look at what this does:
graphql comment on top will be picked up by the module. When the template is rendered, it tries to match the queries input arguments to the current template variables, runs the GraphQL query and passes the result as a new
graphql variable to the template. Simple as that, no preprocessing required. It works for every theme hook. Be it just one complex node type, an exceptional block or
Imagine we use GraphQL Views to add a contextual GraphQL field
similarArticles that uses SOLR to find similar articles for a given node. It could be used immediately like this:
The module even scans included templates for query fragments, so the rendering of the “similar article” teaser could be moved to a separate component:
No preprocessing, a clear path where data flows and true separation of concerns. The backend provides generic data sources (e.g. the
similarArticles field) that can be used by the product development team at will. All without the cost of a fully decoupled setup. And the possibility to replace single theme hooks allows us to use existing Drupal rendering when it fits and switch to the pull-model wherever we would have to use complex layout modules or preprocessing functions to meet the requirements of the project.
There are some ideas for additional features, like mutation based forms and smarter scanning for query fragments, but first and foremost we would love to get feedback and opinions on this whole concept. So if you are interested, join on Slack or GitHub and let us know!