GraphQL And Drupal 10 (Part I)
Welcome to our blog series on Drupal's GraphQL module! In this first part, we will compare the key differences between these two major versions, explore where to start and various ways to write a schema with GrahpQL 4. Later in the series, we will delve into specific topics such as translation, mutation, persisted queries, and decoupling with Gatsby or Next. So let's get started and explore the exciting world of Drupal's GraphQL module!
GraphQL 3 & 4
TLDR: to start a new project, I wouldn’t hesitate for a second – I’d go straight for GraphQL 4. There is no upgrade path between these two major versions, so using 3 and planning to go for 4 would require significant migration work.
If you are looking for a comparison of GraphQL with other options, Dries explains it in this post: Headless CMS: REST vs JSON:API vs GraphQL
Here is a summary of the differences between versions 3 and 4.
For both, we will illustrate with an example of a basic Article node type query.
GraphQL 3
- Provides the schema out of the box, exposing basically everything from Drupal that is content related
- This does not cover Configuration Entities out of the box
- The schema contains many Drupalisms, so it might be harder to grasp by frontenders / API consumers that are not used to Drupal
- The schema can be extended via a Plugin system, mostly Fields and Types
- There is a solution for progressive decoupling with Twig + also a few contributed modules for use cases like preview, formatters, ...
- It relies on a version of webonyx/graphql-php that is not compatible with PHP 8.1. It works fine with PHP 8.0 but as this PHP version will not receive security support after 26 November 2023 and Drupal 10 requires PHP 8.1, this issue needs to be tackled to be Drupal 10 ready. There is a first attempt.
Here is an example query to get an Article by ID.
To get multiple nodes, this can be done with a nodeQuery that will list all node types by default. Here is how to filter by Article node type.
As we can see, it's pretty complete by default and we can get data from the Entity Type (Node) or its Bundle (Article) but this duplication with different field names can be confusing for the API consumer. Because the naming and structure are Drupal specific this can lead to questions for non-Drupal developers:
- Why are entityUrl and body not a scalar (String)
- What is a bundle
- Are entityLabel and NodeArticle.title producing the same values
- Same question for entityId and NodeArticle.nid
- Why do we have body for Article and description for Tag
- Can we query with articleById, or articlesQuery
- What is a TaxonomyTerm
GraphQL 4
- Recommended by the project maintainers
- Developers have to write the schema, the module is mostly a framework to extend and provides a solid foundation of built-in data producers
- There is full control over the schema structure
- The Plugin system is mostly about
DataProducer
andSchema
/Resolvers
Various Ways To Get A Schema With GraphQL 4
Custom, Compose, Core Schema like v3 or Directives, let's see what we get!
Go Custom
If there are only a few parts of Drupal to expose or if the expected query / output is tightly bound to the domain, then this is a good way to go, it's very flexible.
To get started, all that we need is a Schema plugin and then a declaration of the schema in a .graphqls
file. A very minimal implementation is provided in this repository as an example.
Then create a server and head to /admin/config/graphql/servers/manage/minimal/explorer
to execute the query.
To get an Article, the query is stripped to the bare minimum, and is backend agnostic with clearer field names – no need to know what a node, bundle, nid, entityLabel, ... is.
If we use the schema provided by the GraphQL Example module here is how a list of articles query looks. It will use the default limit (10) and offset (0). Neat.
Now let's take a look at what the community offers. At the time of writing, all solutions below are usable but as they are quite recent, they might still contain some bugs. So keep watching their respective issue queue.
GraphQL Compose
GraphQL Compose is sponsored by Octahedroid and inspired by Open Social GraphQL architecture. There is a possible plan to integrate features from v3 contributed modules (metatag, config, ...).
It currently requires this core_version_requirement patch for Drupal 10.
To get an overview of what is covered by the schema, run this query.
Here is how to run the Article by id and Articles queries.
The multiple Articles query provides nodes and edges with cursor pagination (first, last, before, after, ...).
GraphQL Core Schema
GraphQL Core Schema is sponsored by Liip. Its goal is to expose the schema in a way that is close to what v3 proposes, in a more predictable way and with the possibility to configure what is exposed (a bit like what JSON:API Extras is doing for JSON:API in core).
We can configure schema extensions (Node, Taxonomy, Entity Display, Entity Query, ...), exposed entity types and fields.
It provides Paragraphs and Views support and some submodules to get e.g. Metatag covered.
To compare with the v3 query, here is a similar Articles query, with Tags.
GraphQL Directives
GraphQL Directives is sponsored by Amazee Labs. It is a declarative way to build resolvers, so most of the PHP code written in DataProducers
, Resolvers
or Schema
can be delegated to Directives. This is following a similar philosophy that drives Drupal Commerce: do not expose on the UI what a developer can do / won't be touched often and could produce complexity or unwanted changes from less technical users.
What I like about it is the fine-grained way to delegate or write your own resolver, so it provides automation and flexibility over what and how we want to expose.
So a schema that looks like this won't need any custom resolver.
If a field requires a custom resolver that is not reusable, the directive just needs to be omitted and the custom resolver implemented as usual.
If we need to create a new directive, it can be declared via a Plugin system.
Similarly, for Metatag, we could declare it like this:
Then we can provide the type definition of what we want to expose.
As this article is limited to an overview of what currently exists, a complete example based on Directives will be elaborated on in another post.
Documentation
Where to Start
The Drupal documentation is mostly about v3, for documentation that covers both versions, use this Gitbook documentation to get started.
The example modules shipped with the GraphQL module are also a pretty good starting point.
Also to note: the GraphQL module issue queue is on GitHub.
Where to Continue
For an exhaustive introduction to the GraphQL module, make sure to watch Building a GraphQL API - Beyond the basics DrupalCon Portland 2022 from Alexander Varwijk (@kingdutch). It comes with this repository.
Open Social and Thunder distributions are inspiring, checking the implementation of both is really worth it to get a deeper understanding of schema building.
In Closing
I'm really excited about the variety of options that the community offers, demonstrating the incredible versatility of GraphQL in Drupal. These options provide the freedom to address various use cases and give developers expressive methods to construct their APIs.
If you're excited about harnessing the power of Drupal's GraphQL module, stay tuned for the next instalment. In the meantime, feel free to explore the resources we've mentioned and start building your own GraphQL-powered projects. Happy exploring and reach out to us if you have any questions!