Use yarn workspaces to share a tailwind config file throughout your WordPress application

I don’t think I’ve done a site build in the past couple years that didn’t include at least one “site-specific” or “core functionality” plugin. Since the advent of Gutenberg this has gotten way more pronounced and, recently, the need to share front-end modules between themes and numerous editor-focused plugins has grown from a “would be nice” to a total do-or-die affair.

There used to be a really clear hierarchy to the WordPress developer environment, with the site’s theme being the most central, important component. Now, that hierarchy is a whole lot less clear to me. And it’s not just me, either. Auttomatic just opened a repo to kick off the process of redefining what a theme is in our new blockular world.

Long story short, where containing front-end builds within the themes directory made imminent sense this time last year, now it doesn’t really sit flush with my typical workflow.

“It sure would be nice if I could share configurations between the site’s plugins and its theme…”

This all really crystalized on a recent site build utilizing tailwindcss. And while I’ll be using that (compiled with Laravel Mix) as a case study in this article, all of this definitely has application in absence of those tools. You could use it with bootstrap, bespoke javascript components, accessibility testing tools — really almost anything you might find yourself needing to re-use throughout WordPress.

The only thing that’s really critical to understand about tailwindcss for our purposes is that it compiles a utility-first stylesheet from a JS config file, and that I wanted to share that config file between some plugins and my site theme. If you’re using tailwind properly, you’ll be changing this configuration file far more often than you’ll be writing CSS that utilizes it, and it has to be recompiled on every change.

This is a recipe for frustration. Even with some clever bash scripting to copy and recompile the new config, you’re still looking at a really onerous and considerably lengthy build process. Once you get up to, like, two or three plugins it basically becomes intolerable.

Enter Workspaces

Workspaces is a new-ish feature of the yarn package manager that functions like a really light-touch version of lerna. Basically, it makes working with monorepos less of a pain in the ass. Yes, if you’re still reading this, your WordPress is probably best considered a monorepo. Most of the WordPress sites I have built or help out with could fairly be described as a Laravel application with several small React applications unceremoniously bolted on. Gutenberg is itself a monorepo and it utilizes Lerna to help manage that complexity.

Workspaces is going to let us get to a place where we only have to run our npm compilation scripts once, at the root of the repository, rather than in every single directory that needs to be built. It will also give us a super useful way to reuse application modules from other workspace directories – which is how I got here.

Let’s do it.

To get started you’ll need to make a package.json file in the root of your project that contains, at minimum:

  • A name
  • private set to true
  • an array of project directories that make up your workspace.

Here’s a sample:

Each one of the directories should contain a package.json file. At minimum this should contain a name. If it utilizes dependencies it should contain those dependencies. It’s really just a normal node package file at the end of the day, so just treat it as you normally would or need.

For my purposes, I’ve elected to configure tailwind right in Bedrock’s /config alongside application.php. I mean, it is a config file. Here are the JS contents of /config:

Now, in my theme, I can just bring the preconfigured tailwind instance from /config in with a simple require statement. Yarn has already aliased the tailwind object being exported from that workspace. The alias is always the name defined in package.json.

So, problem solved! But let’s take advantage of one other feature of workspaces before we call it a day – a unified set of npm scripts to build the entire WordPress and all of its components in a single go.

There are many ways to handle running parallel node scripts. One of the more popular ones is concurrently, and that’s what I’ll be using here. The following assumes all of your components utilize yarn start to kick off development and yarn build to produce a bundle and yarn build:production for situations like building as a part of CI.

Now you can run a yarn build in your project root and watch as the entire thing gets built out in one go. Should you ever need or want to just build one part of your application, that’s fine as well.

Also, all of your workspaces are now sharing a single node_modules directory (except for binned dependencies). So if you had twelve copies of all the dependencies used by create-gutenblock or wordpress-scripts you’ll probably reclaim a big ol’ chunk of harddrive space.

Hope this is helpful to y’all!

Keep’ on keepin’ on! 👍🏼