Part 1 | Part 2
At DrupalCon Amsterdam 2019, Fabian Franz (Senior Technical Architect and Performance Lead at Tag1) delivered a session entitled "Components everywhere: Bridging the gap between back end and front end" that delved into his ideal vision for enabling such shared components in Drupal's own native rendering layer. Fabian joined Michael Meyers (Managing Director at Tag1), and me (Preston So, Editor in Chief at Tag1; Senior Director, Product Strategy at Oracle; and author of Decoupled Drupal in Practice) for a Tag1 Team Talks episode highlighting the progress other ecosystems have made in the face of this problem space and how a hypothetical future Drupal could permit rich front-end developer experiences seldom seen in the CMS world. In this two-part blog series, a sequel to Fabian's DrupalCon session, we dive into some of his new conclusions and their potential impact on Drupal's future.
Components everywhere in Drupal
At the onset of our conversation, Fabian offered a quick summary of his idea behind components everywhere—i.e. shared across both client and server—within the Drupal context. The main thrust of Fabian's vision is that developers in Drupal ought to be able to implement a back-end application in a manner indistinguishable from how they would implement a front-end application. In other words, developers should not necessarily need to understand Drupal's application programming interfaces (APIs) or decoupled Drupal approaches. By decoupling Drupal within its own architecture (as I proposed with Lauri Eskola and with Sally Young and Matt Grill before that), we can enable the implementation of purely data-driven Drupal applications.
But what does this truly mean from the standpoint of Drupal developers? Fabian identifies the moment where components everywhere will truly reach success as the conditions in which the same component can be leveraged on the front end and back end without any distinction in how data is handled. One of the key means of doing this in a way that can be shared across client and server is through slots, which can contain additional data and provide the concept of component "children."
Because of how Drupal's front-end architecture was originally architected, there are significant gaps between how Drupal handles its "components" and how other technologies juggle theirs. For instance, while theme functions comprise an important foundation for how Drupal developers interact with the Drupal front end, there is no way to provide a slot for interior data or nested components. There is an analogous concept in terms of children in the render tree, but this requires considerable knowledge of PHP to traverse. According to Fabian, though we have all of the elements needed for a component-based system available in Drupal, one of the primary challenges is that there are so many elements within Drupal that can lend themselves to such a component-based system.
Looking to Laravel for inspiration
Adhering to the open-source philosophy of "proudly found elsewhere," Fabian turned to other projects for inspiration as he began to articulate what it would take to implement the vision he presented in Amsterdam. After all, reinventing the wheel is usually an ill-advised approach when open-source solutions are available to be leveraged. For instance, Laravel contains templates but needed to introduce component tags to their templating system in order to capture generic slots. In Drupal, on the other hand, both theme functions and Twig templates can morphologically be considered components, but they lack certain key attributes most components today contain. Slots are implementable in Twig, but that is solely because all data is already available to Twig templates in Drupal.
Laravel 7 introduced BladeX to the Laravel ecosystem. BladeX provides a highly enjoyable developer experience by serving as a component handler for Laravel components. As long as developers prefix all components with
x- in their custom element names (i.e.
<x-component>, they no longer need to use a regular expression to find all possible component names in the component system, instead simply searching for all components whose names are prefixed with x-. And if the React developer experience is any indication, many modern front-end developers strongly prefer declarative HTML like the following:
BladeX first began as a contributed plugin to Laravel. Later, it was added to Laravel core due to its usefulness in enabling not only a graceful component system but also pleasant-to-use syntax to work with those components. Livewire also includes graceful capabilities enabling interactivity, which in Drupal is currently represented by the Drupal Ajax framework (difficult to use due to its tight coupling to Drupal's Form API).
More recently, Laravel introduced a tool known as Livewire, which makes it possible to implement server-side document object models (DOM) but lacks the data input/output (I/O) necessary to enable state management and interactivity. As such, Fabian extended the concept of a store from his DrupalCon session to include a provider that allows data retrieval and use in components. Fortunately, Livewire has a partial implementation of this, and it is possible to implement a server-side message that increments a counter and then to retrieve that counter value gracefully from the client side. Livewire automatically understands that it needs to update the server-side render of that counter and serve that updated value to the client.
What about Web Components?
Fabian's thinking is by no means alone when it comes to enabling components everywhere in Drupal. Many other initiatives, including one that aimed to introduce Web Components into Drupal, have been down this road. But why are Web Components so compelling for this in the first place? By going a step further and introducing the Shadow DOM, Web Components can provide full encapsulation automatically, off the shelf.
In this blog post, we examined some of the new conclusions Fabian has come to well after his DrupalCon presentation when it comes to enabling components everywhere in Drupal, particularly taking inspiration from other ecosystems like Laravel, React, and Web Components. In the second installment of this two-part blog series, we'll dive into how to define components in Drupal, offer a more declarative component experience when working with them, and some of the other ways in which we can enable shared components across client and server and rich immutable data-driven state in a setting where these novelties have long seemed to be anathema or worlds removed: the Drupal front-end ecosystem.
Part 1 | Part 2