Part 1 | Part 2
Emerging approaches to front-end development portend a very different world from the one we live in today with regard to handling and juggling components. After all, new best practices promulgated by the likes of JavaScript technologies like React are overturning our preconceived notions about components and our foregoing definitions. For instance, React now contains both declarative rendering of components through JSX and efficient document object model (DOM) diffing through the concept of Virtual DOMs. Despite all of this progress, however, content management systems (CMS) like Drupal and others have not kept pace with the rapid change in how components are realized in front-end ecosystems. Can they ever catch up?
Fabian Franz (Senior Technical Architect and Performance Lead at Tag1) presented a well-attended session entitled "Components everywhere: Bridging the gap between back end and front end" at DrupalCon Amsterdam 2019 that articulated his dream vision for shared components across back end and front end in Drupal's own native rendering. He recently rejoined 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 spotlighting some of the ways in which his thinking has evolved since then and what Drupal will need to do to enable a more robust component-driven rendering approach ready for the future. In this second installment of this two-part blog series, we examine what Drupal's next steps may need to be according to Fabian's vision in order to facilitate components everywhere.
Next steps for Web Components
Before proceeding, I recommend that readers interested in this topic check out the first installment of this blog series to gain all the background and context necessary to proceed. We ended the first installment of this two-part series with a discussion of how novel CSS paradigms are challenging long-held ideas about how to control components from the standpoint of their presentation. But there is also another key characteristic of components that we need to scrutinize: whether it is a layout or style component.
In Web Components, the distinction between layout and style components is realized in the Shadow DOM thanks to effectively scoped CSS. But unfortunately, Web Components are not declarative in that they are JavaScript-only and require you to load your component first through the Web Components API and then ensure that the browser can display said component correctly. According to Fabian, the ideal vision for Web Components is one in which the Shadow DOM can be leveraged declaratively and without any JavaScript needed whatsoever. Despite the fact that shims exist that can automatically traverse Shadow DOMs to find components (e.g. an <x-shadow-root>
element), declarative Shadow DOMs are extremely challenging to implement, particularly when server-side rendering enters the picture.
Another recent project of interest to Fabian is Tome, a static site generator created by Sam Mortenson that integrates deeply with Drupal's render pipeline. According to Fabian's analysis, Sam succeeded in implementing a Shadow DOM analogue in Tome through classes, each of which approximated a Shadow DOM-like approach effectively enough to render an analogue to the component on the server. This got Fabian thinking. Because Web Components is still missing some crucial details, he admits that to implement a declarative Shadow DOM himself, he would leverage an abstraction for components (rather than Web Components) that would allow for a later distinction of React, Vue, or Twig as the renderer of that component. According to Fabian, the data flowing into a component is of far more importance than who is displaying or rendering it.
Taking inspiration from Inertia.js
Another project Fabian has taken inspiration from is Inertia.js, a JavaScript library that begins to approach Fabian's ideal goal of being able to write a single-page application without a single line of JavaScript. With bindings for Laravel and other server-side technologies, Inertia.js allows developers to write normal controllers as they are used to on the server side and set them up in such a way that they return data. As such, if only the data in a component changes, the templates will change on the client side, and the data can be fed to Vue or other frameworks for ingestion. Meanwhile, if the entire context of a component changes, Inertia.js will undertake a full server-side request.
Fabian believes that Inertia.js doesn't go far enough, because it focuses on the notion of individual pages rather than the highly granular page components in which Drupal trafficks. In Drupal, for instance, there are blocks and forms that occupy portions of the page but that each leverage their own complex APIs. Thanks to the Dynamic Page Cache module in Drupal 8 (also leveraged by Wim Leers' RefreshLess module), we can identify how similar a page is to a particular page layout and only update those page sections that have been modified.
Next steps for Drupal
Well after the conclusion of his talk, Fabian returned to his ideas and clarified for himself what would be required and what could be descoped from a "components everywhere" feature set. Many technologies he investigated since his DrupalCon Amsterdam session solve only one part of the problem he has outlined and provide robust approaches for those problem spaces. This led Fabian to recognize that the need to start simple is paramount. For instance, he confided in our recent Tag1 Team Talks episode, Drupal could theoretically learn significant new knowledge from Laravel's renderer and leverage their syntactic features for Drupal's own Components module, created by John Albin Wilkins.
After DrupalCon Amsterdam, there was considerable interest in "components everywhere" in Drupal, but Fabian also acknowledged that the level of interest from the community was much higher than that from core maintainers. Fabian next plans to look to the wider front-end community for next steps to move the proposed vision forward. And he planned to deliver a session at Frontend United in Minsk about those subsequent steps. Fabian still believes that his vision of completely decoupling the data is more difficult than something akin to Livewire where data definitions and data updates are both present within the same component.
Distinguishing interactive components
Drupal has a substantial opportunity to offer a means of registering components that have dynamic versus static data (that does not change unless a full-page request is executed). Similarly to how Dynamic Page Cache currently provides an initial skeleton that is then fleshed out with progressively more data to fill out the components in question, Drupal could define a means for components to indicate less need for rehydration than others. Moreover, Drupal could facilitate the creation of static pages without any JavaScript whatsoever for pages having only components that work with static data.
Because determining interactivity is something the front-end development world has not solved completely, Drupal could take the lead in allowing developers to resolve automatically what portions of pages need to be interactive or not. Fabian even envisions the possibility of a language in which we could declaratively assign interactivity to particular blocks on a page that are considered components. A scenario such as one in which a block should be more interactive due to a button lying therein that updates block content to the most recent version would be readily solvable under this approach. Giving the developer the ability to specify the level of interactivity of their components would not only lend greater power to defining cacheability but would also reduce the need to push the entire DOM tree to the page rather than only the portions that have changed.
Interactive components in other ecosystems
Other ecosystems indicate that this thinking is nothing new. After all, React's new hooks API attempts to approximate a typical page request, and Fabian argues that the core idea behind both GraphQL and React hooks is the ability to write code as if it were a traditional PHP application again. He believes that Drupal has significant opportunity at the moment to reenter the front-end landscape and reinvent the front-end developer experience in Drupal, thanks to the inspiration represented by ecosystems like Laravel, a frontrunner in front-end innovation when it comes to open-source successes.
Conclusion
Components are nothing new to front-end developers, but they have undergone such substantial evolution from a conceptual and technological standpoint over the last decade that they are virtually unrecognizable to traditional content management systems like Drupal that have retained a server-oriented approach to component management. When it comes to JavaScript, on the other hand, technologies like React have shown that the modern front-end developer experience must involve declarative rendering and Virtual DOM-driven diffing. Moreover, a shared sense of components across server and client are needed to enable universal JavaScript applications and to contend with a world in which data can be rendered in virtually any environment and by any system.
In this two-part blog series, we identified some of the ways in which next steps for Web Components and for Drupal could take inspiration from technologies like Laravel's Livewire and Inertia.js as well as React's JSX and the Shadow DOM. Fabian recommends anyone interested in component-driven front-end development in Drupal to join the #components channel in the Drupal Slack, where he will work to formulate a more formal proposal for review. In addition, Fabian recommends that developers take a look at BladeX and whether a similar x-
prefix for Drupal components could be possible, such as <x-entity>
. What would a simple alert or other Web Component look like in this context? It may still be early days for components everywhere in Drupal, but the initial steps are uniquely promising.
Special thanks to Fabian Franz and Michael Meyers for their feedback during the writing process.
Part 1 | Part 2
For more on Web Components and how they're being used, see Web Components.
For all of our Laravel content, click here.
Photo by Raul Cacho Oses on Unsplash