Decoupled Drupal — The holy grail! Or not!
Agreed, decoupled Drupal is awesome. It gives great opportunities to build omnichannel, inviting, flexible and interactive applications which are totally 2020! To be honest, it is great that Drupal finally took the leap with creating a API first CMS and adding JSON:API to core. However, in my journey on creating rich internet platforms, websites and applications based on Drupal, I found out that decoupled Drupal is not (always) the holy grail. In fact, it can really turn out into a maintenance nightmare.
What is decoupled Drupal?
For a lot of people among us, decoupled Drupal, or headless Drupal, is a known term, but let me explain it for the lesser introduced reader.
According to Acquia decoupled Drupal can be explained as:
This just means that, while using Drupal as a content management system (CMS), you can use a frontend framework like React, Vue or Angular to create the frontend and get all data from Drupal using webservices, GraphQL, etc.
In this article I won't give you my opinion, I'll keep that to myself for now. I will however give you pointers you need to help you decide if a decoupled website is something you need for a project, or in general.
When you are thinking about doing a project (progressively) decoupled you need to know a few things in advance. Like, what kinds of (de)coupled are there?
This is the most obvious choice. A coupled Drupal site means that all of your site is being rendered through Drupal. You are using twig templates, the Drupal render engine and Drupal as the data provider without the use of webservices. This is how we are building Drupal sites for a long, long time now. So nothing changes.
When you are a developer who wants greater control over the frontend this is the most appealing option.
A fully decoupled website also makes it possible for you to generate fully decoupled static sites. The static site generators (like Gatsby) retrieve content from Drupal, generate a static (HTML version) of the website and deploy the site.
When to use (progressively) decoupled (or not)
One of the first things you need to do before deciding what technique to use is to determine what you are going to build and for who.
Let's be clear, for single instance websites it might not be the best choice to go (fully) decoupled. However even single instance websites may need some parts, or even the complete website to be decoupled. Just because you want to be able to give the end-user the best possible interactive experience.
If your customer requires you to build more then 1 web applications (corporate websites, online working environments, etcetera) a decoupled Drupal could be the perfect fit. You can use it solely as a content repository that provides data to several consumers, or even use Drupal as a coupled environment that also exposes the content to other consumers.
When building a omnichannel experience where you need to be able to provide content to both web and non-web applications (like native mobile apps) you can use Drupal solely as a content repository that provides the content for all those consumers. Maybe even part of the infrastructure behind a ESB or ETL.
The nice thing about doing decoupled with Drupal is that it can provide them all. And they are (in most cases) not mutually exclusive.
When making the choice to go for decoupled you need to have answered some questions for yourself.
If the project needs to access data from multiple sources via an API you are probably best of using a progressively decoupled site. This way you can use the Drupal theming layer to render the content provided in Drupal, and partially use decoupled “widgets” that show the data provided by the different API’s.
Again, these options are not mutually exclusive and fixed for the future. Even if you create a coupled Drupal website you can eventually expose it’s data and use a client like a mobile app or a web application to retrieve that data. You can even build a complete new decoupled frontend for the existing website without to much hassle for the Drupal developers.
Why should I decouple?
In last few years I’ve heard several developers say that decoupled Drupal was the way to go. But is it? What are specific advantages of going fully decoupled?
When decoupling Drupal you can do independent upgrades of the visual design without any backend changes. Just re-use the same API’s and redesign and rebuild the site and everything should be fine. The same goes for the backend. As long as the output of the API stays the same, the frontend should be able to keep running when replacing the backend.
You are not all reliant on Drupal developers. For me as a Drupal developer, this is hard to say, but when building a decoupled Drupal site you need less Drupal specialists. Just because the frontend isn’t built in Drupal and there is a clear line between the frontend and the backend.
Content creators can focus on what they can do best, create content. They don’t have to be focussed on how the content eventually will look because the consumers (mobile apps, websites, etc) are responsible for this.
The API’s can grow to bigger and be consumed by multiple consumers without worrying about the frontend. The API is documented and can be made available to your other projects, third-parties or the public with not much effort.
Why shouldn’t I decouple?
In last few years I’ve heard several developers say that decoupled Drupal was the way to go. But is it? What are specific disadvantages of going fully decoupled?
What you need to understand is that a coupled website is simple architecture. You only have 1 system, namely Drupal that you need to maintain, understand and debug. When you move to a decoupled architecture you need to keep in mind that it is more complex. You need to maintain multiple systems, need to understand what’s going on between them, and finding bugs gets more difficult because you need to figure out where the bug is actually coming from.
When maintaining and adding functionality to the decoupled application you need to be able to keep in mind that there is a strict separation of responsibilities between the systems. You should not add display logic to the webservices. This prevents circular dependencies, and prevents you from being able to swap CMS-es.
When you are used to developing coupled websites with Drupal you are used to the out-of-the box functionality that Drupal contributed modules give you. Modules like “Views infinite scroll”, “Redirect” or “GoogleTagManager” all have integrations with the frontend, and some even with Drupal users and permissions. All these functionalities need to be re-written in the frontend.
When using forms in the website, and in particular using webforms or the cores contact module, you need to rebuild the rendering, validation and submitting functionality in the frontend. While Drupal takes care of this by itself, you also need to get CSRF tokens because Drupal won’t accept POST requests without them.
Next to the contributed and form functionalities, you also need to keep in mind the basic core functionalities. When your end-users need to be able to view restricted content, so they need to log in, you need to be able to build a safe authentication method. Also editors aren’t able to preview the content to see how it looks like on the actual site. Well, they can, but then you need to create the frontend in Drupal, and that beats the decoupled purpose.
UI translations are something else, this is a functionality that has to be built yourself. While Drupal provies this (you can translate all kinds of UI strings) that just works on multilingual sites.
How do I decouple?
How to decouple is partially based on your own preferences. You have multiple options to choose from when choosing technologies for the backend (what webservice for instance) and the frontend.
Part of this decision is deciding if you want to use a static site generator like Gatsby. Google to see what the benefits are of this option, in this article I won’t go into depth in this topic.
Here you have multiple picks that each have their ups and downs. I will mention a few of them. But this isn’t a full list of options.
When working with Drupal version > 8.7 you have the option of JSON:API in core (older versions can use the JSON:API module). JSON:API exposes all entities in Drupal in the JSON:API specification. However, this doesn’t give you everything, because not everything is a entity. But this is something you can overcome.
You can use the GraphQL module. This makes it possible to execute GraphQL queries on Drupal and retrieve your content, menus, etcetera like that. Lots of frontend frameworks have plugins or modules that you can use to execute these queries. Apollo GraphQL is one of them.
Another option is to build the REST services yourself. Drupal makes it possible for you to easily create REST resources in where you can write your own functionality just the way like or need it. This is possibly the most work intensive choice, but does yield the most specific result for your application.
What you don’t want is a webservice that is open to everyone. You can enable and configure CORS (and you should), but you should also use authentication.
Drupal out-of-the-box provides two kinds, either via cookies or via basic authentication. For decoupled basic authentication is the only one of the two you can use. With this method selected you just send a extra Authorization header on each request with the encoded username and password of the user you want to use. When your backend contains sensitive information, or content that shouldn’t be available for everybody, this might not be the most safe method. The username and password are encoded via base_64, so can be decoded easily.
A better way to provide secure authentication is through oAuth or key authentication.
For oAuth there are multiple contributed modules on Drupal.org (take a look at the list on d.o). With oAuth it is possible to use per-user authentication, let access tokens expire, and lots more. This is a perfect method to use for user authenticated environments like intranet applications because tokens gets expired after a period of time and users need to refresh them what can only happen if they have a session in Drupal.
Key authentication works in a different way. You can see this as API keys for Drupal. A user can generate a API key for itself and this can be used in the frontend application to access webservices. Unlike oAuth this key doesn’t expire after time, but can be revoked by the user, or a admin user. This is perfect if you have non-personalised data you want to expose via the webservices and works like every other API key like you can generate for, for instance, Google Maps.
Is decoupled the holy grail?
Short answer: no.
Long answer, no but… In some cases (progressively) decoupled Drupal is certainly the way to go. Especially if you have a omnichannel architecture, decoupled fits really well. And in some cases it’s just too much.
As far as I’m concerned you need to look at every project separately and determine for each project if you need it to be decoupled, and if so, in what kind of form and shape. And if in doubt, do not decouple. You can always make the choice to decouple on a later stage, or to expose webservices from Drupal to consumers that are built later on.
For me decoupled Drupal is really great. A nice developer experience and you can build great interactive applications and I really love learning and building in that way. However, I’ve also learned (the hard way) that it’s maybe not always the best way to go. And can give you a lot of stress, more complexity, and a maintenance headache.
Just investigate, see what you want, what your team wants and can do, what your customer expects and wants and take a look at future plans, if there are any. Just make sure that your decision isn’t based on how hyped a certain technology is.