Don’t Push it: Using GraphQL in Twig

Using GraphQL in Drupal with Twig instead of React, Vue or the next month's javascript framework might sound like a crazy idea, but I assure you it’s worth thinking about.

Twigs of grass. As in Twig the template language.

Decoupling is all the rage. Javascript frontends with entirely independent backends are state of the art for any self-respecting website right now. But sometimes it’s not worth the cost and the project simply does not justify the full Drupal + React technology stack.

Besides the technological benefits of a javascript based frontend like load times and responsiveness, there’s another reason why this approach is so popular: It moves control to the frontend, concept and design unit, which matches project workflows a lot better.

Status quo

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 node.html.twig:

 

This is already enough to pull the information we need and render it. Let’s have a look at what this does:

The 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 page.html.twig.

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:

node.html.twig

 

node-teaser.twig

 

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.

Future development

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!

January 15, 2018
6 Comments

Get our Newsletter

Comments

As the author of that issue you linked (https://www.drupal.org/project/ideas/issues/2702061), I think this is very much worth exploring, and probably an excellent fit for certain use cases!

I hope some Drupal agencies adopt this for their client projects.

By Wim Leers
4 weeks ago

Glad to hear your opinion! We are currently using it partially (mixed with traditional rendering), which works fine and helps a lot to find issues. And the next step will be an example consumer for contenta. Yes we are going to re-couple.

By Philipp Melab
4 weeks ago

what about asynchronous data?

By josue
4 weeks ago

Asynchronous as "on the client side"? Just use whatever javascript framework you used before. This is just about Drupal rendering.

By Philipp Melab
4 weeks ago

Thanks for the article. An obvious disadvantage of query in the twig comment is the lack of IDE support for such concept in the moment. Do you have some technique to deal with that?

By Miloš Kroulík
3 hours ago

I forgot to mention that: If you place a file with the same name and an additional *.gql extension right beside the twig file (e.g. node.html.twig.gql) it will be picked up as if it where in a comment. Then the IDE should kick in.

By Philipp Melab
29 minutes ago

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
icon
What is Amazee Labs?