Pattern Lab and Drupal 9: Prepare your theme for Twig 2

Web development

Drupal 9 was released just over six weeks ago and heralded as the easiest major version upgrade in a decade. But for those of us using Pattern Lab as a pattern library for component-based development, it’s a little more complex.

As you may already know, the largest difference from a theming standpoint between Drupal 8 and Drupal 9 is that the latter uses Twig version 2. This means two things:

  1. Your Twig files need to be purged of anything that was deprecated in Twig 1 and therefore no longer available in Twig 2.
  2. Your composer build must use Twig 2 and that all your packages must be ready to use that version. 

From the Drupal side Twig is already completely upgraded to version 2 in core, and many contrib modules as well. This is just not the case with Pattern Lab. In this tutorial we will walk you through some steps that we hope will ease your journey to getting your Pattern Lab integrated theme working in Drupal 9.

 

Drupal 9 Specific Changes
 

Step 1: Core Version Requirement

This is simple and you may have already done this, just add/change core version requirement in your theme’s .info file:

core_version_requirement: ^8.9 || ^9

Step 2: Upgrade to Components! 2.0

The Components! module is crucial for the namespacing that component-based development requires and so it must be upgraded. Components 8.x-2.0-beta3 was released a week ago, and it is the first release that is fully Drupal 9 compatible.

composer require 'drupal/components:^2.0'

drush en components -y; drush cr

Step 3: Update other modules

We use twig_tweak and twig_field_value so just to be on the safe side we upgraded those. Twig_tweak has had Drupal 9 compatibility since version 2.5 (current stable is 2.6) and twig_field_value’s Drupal 9 compatible release is 2.0.0.

Good news! That was sufficient to get our Drupal 9 profile running in the browser!! 

But what about Pattern Lab? Our Pattern Lab instance seems to work okay, but let’s take a look under the hood to be sure.

 

Pattern Lab Specific Changes
 

Step 1: @basalt/twig-renderer

What is @basalt/twig-renderer and why should I care, you might ask. Well, it’s the twig renderer used by the current version of Pattern Lab engine-twig-php (5.11.1 as of this blog post).

 "dependencies": {

   "@basalt/twig-renderer": "0.13.1",

   "@pattern-lab/core": "^5.11.1",

   "chalk": "^4.0.0",

   "fs-extra": "0.30.0"

 },

But what version of Twig does @basalt/twig-renderer use? Well, that takes a little sleuthing to track down. In my downloaded package there’s a /vendors directory and no composer.json in @basalt/twig-renderer. But there is this informative line in the scripts section of package.json:

"prepare": "composer install --no-dev --optimize-autoloader --prefer-dist",

Aha, so there is a composer.json, just not part of the installed package.

"require": {

  "ext-json": "*",

  "twig/twig": "^1.41.1",

  "react/http": "^0.8.3"

}

At least Twig 1.41.1... But we need ^2.0 for Drupal, and how do we do change a dependency’s dependency?!

First we need a version of Twig renderer that has Twig 2 as a dependency. Well, as of June 4th, there is: https://github.com/knapsack-cloud/twig-renderer/tree/v2.0.0 

Second, how do you change a dependency of a dependency?! Well, there’s a package for that! 

Its usage is relatively simple. First add a resolutions section to your package.json:

 "resolutions": {

   "@basalt/twig-renderer": "2.0.0"

 }

Next add npm-force-resolutions to the preinstall script:

"scripts": {

  "preinstall": "npx npm-force-resolutions"

}

Lastly, just run "npm install" as you would normally do.

Please note that because npm-force-resolutions runs as part of “preinstall”, if you delete your package-lock.json BEFORE you "npm install" you will have to run "npm install" twice.

And to confirm the version of @basalt/twig-renderer:

npm ls @basalt/twig-renderer

You should get output similar to the following:

$ npm ls @basalt/twig-renderer

particle@10.5.0 /Users/adamjuran/Sites/1xdx9x/web/themes/custom/particle

└─┬ @pattern-lab/engine-twig-php@5.11.1

  └── @basalt/twig-renderer@2.0.0  invalid

npm ERR! invalid: @basalt/twig-renderer@2.0.0  .../web/themes/custom/particle/node_modules/@pattern-lab/engine-twig-php/node_modules/@basalt/twig-renderer

The invalid response is an indication that this is not the ACTUAL dependency of @pattern-lab/engine-twig-php, but we knew that.

Now we have Pattern Lab itself rendering Twig 2 just like Drupal is! But we’re not done yet…
 

Step 2: Syntax, syntax, syntax...

Now, you might still be getting some errors when building your pattern library or viewing your Drupal site. This might be because there are significant syntax changes between Twig 1 and Twig 2. Fortunately this very informative guide outlines these differences for both templates and modules.

As it turned out, our version of Particle was already almost fully Twig 2 compatible, with only a few minor cases where we replaced the deprecated raw filter with its successor, the verbatim filter. 

That should be it! While I can’t guarantee that your particular Pattern Lab integrated theme works in Drupal 9, I’m very hopeful that you are a whole lot closer. Good luck and happy coding!

Special thanks to my colleague João Ventura, Chris Bloom of Phase2, and Evan Lovely of Knapsack Cloud, Ofer Shaal of Palantir.net, and Mario Hernandez of Mediacurrent for their help in preparing this article.