There’s so much goodness coming to the developer experience in Drupal’s front-end! Over the past view months, I’ve written blog posts on a better dumping of Twig variables, a responsive grid in Views, and the new |add_suggestion Twig filter
.
But the thing I’m excited most about in the pipeline is single directory components in core.
Background
Drupal’s front-end is a bit old school in its separation of concerns. We place template files into one directory, stylesheets into another, and scripts into yet another. This means that when a developer works on one component, they need to 1) use Twig debug to find the template, 2) search the codebase for the relevant CSS file (or partial), and do the same for the JS. In addition to all that, the developer may need to edit or modify the libraries file and preprocess functions. This is a lot to take in!
Newer frameworks (including many in the JavaScript ecosystem) make things easier. Instead of separating markup, CSS, and JS by filetype, they’re separated into components. This makes things much easier for frontend developers! Finding related files is much easier, bouncing between these files is simpler, and components can be easily shared across projects by copying and pasting between projects!
Solutions in contrib
Contrib developers have been solving this problem for a long time. Pattern Lab was popular for a very long while, but the PHP version is no longer maintained. Other solutions such as Fractal, and Emulsify (which is a great solution that utilizes Storybook) are also commonly used, but they have limitations such as relying on a (somewhat nonstandard) JavaScript version of Twig. In addition, integrations with Drupal are not very tight. Custom Twig filters and functions have to be recreated so the components render within the component preview system.
Recently, Lullabot’s Mateu Bosch (e0ipso on Drupal.org) created the CL Components module. This solves many problems by letting Drupal directly render the Twig files (instead of relying on TwigJS) which also allows the direct usage of Drupal’s render pipeline.
This is great… but it’s still not in core. This means that many developers won’t know that it exists, in addition, there’s lots of duplicated efforts between the different approaches.
Backward compatibility in core
At the same time, core front-end framework manager Lauri Eskola has been discussing the problems of backward expectation with the libraries system in Drupal core for a long while.
The gist of this problem is that all CSS and JS must be added through creation of a library. However, a core library creates an expectation that it can be reused. And if it’s being reused, that means that core cannot change the styles without breaking backwards compatibility. This limits Drupal core’s forward momentum.
Lauri created an issue to allow direct attachment of CSS and JS to templates without creating a library (see https://www.drupal.org/i/3050386) to work around this expectation.
Initial discussion
In that issue, Mateu popped in to share the method he uses to solve this problem within CL Components. He had recently been showing off all of the excellent work and I suggested that we get everyone together to formulate a plan on bringing this work into core! We also grabbed Acquia’s Wim Leers and Lullabot’s Hawkeye Tenderwolf because of their excellent knowledge of Drupal’s render system’s internals.
Our goal is to 1) solve the aforementioned backwards compatibility problem in core, and 2) improve the developer experience by allowing single directory components in core.
We had two Zoom meetings (note Wim only made the first), where we discussed the pros, cons, potential blockers, and edge cases of various approaches to bringing this into core. After these long and in-depth discussions, we collaborated (by collaborate, I mean it was mostly Mateu!) on a Google doc to create the initial issue.
What could this look like in core?
Please note that this plan will likely change as the issue gets more eyes and opinions in it.
A component’s directory will live under the theme/templates/components
directory. They’ll be automatically discovered. Within that directory, we’ll have a Twig file, CSS file, JS, and a YAML file that contains metadata, such as the files, version, name, description, etc.
Components can override other components (see the issue for more details), and they can be invoked similarly to the way current contrib component approaches work (by having a “mapping” template with a Twig include
or embed
that calls the component).
{{ include('my-component', {
prop1: content.field_foo
}) }}
If we don’t want to create the mapping template, the component may have a useIn
key that tells Drupal when to use it!
useIn:
node--teaser:
componentProp1: content.label
componentProp2: content.field_image|render
There are many more details including automatic library creation, component negotiation, and edge cases in the core issue at https://www.drupal.org/i/3313520.
Timeline and how you can help
If there’s ever a time to bikeshed, this is it! We’d love to hear your thoughts and ideas (even if it’s just a big +1)! If you’re a backend developer, who has knowledge of Drupal’s render internals, please speak up! We’re going to need lots of help writing and reviewing code.
This definitely won’t make it into core by Drupal 10.0.0 (which is coming in a few short months), but we hope to have it in by 10.1.x, which is planned for June 2023. This goal is very ambitious, but we’re all really excited, and we think the Drupal community will be, too!
Hey you! Leave a comment!
Seriously... I really like it when people let me know their thoughts and that they've read this.