Easy build tooling with Bud.js

In the past year I was doing some work for a client where I was taking over maintenance of their Wordpress install. The previous devs had used Sage, a framework I was familiar with… but also, the version they’d used was pretty old, and furthermore, old to the point that the build tools used in that version were no longer maintained. Moving the whole thing over to the newest version of Sage seemed more trouble than it was worth given the changes to templating, but I wanted to see if there was stuff I could borrow and back-patch in.

The newer versions of sage use Bud for asset compilation, which is a build tool that’s so weirdly easy to use sometimes that I often forget it just… works. I installed bud and then also the plugins bud-imagemin, bud-postcss, bud-preset-wordpress and bud-sass, put together the bud.config.mjs file, and then set the package.json build script to run yarn bud build. And this is all that I put in bud.config.mjs:

 * Build configuration for bud.js
 * @param {import('@roots/bud').Bud} bud

export default async bud => {
   * The bud instance
     * Set the project source directory
    .setPath(`@src`, `assets`)
    .assets(["images", "fonts"])

     * Set the application entrypoints
     * These paths are expressed relative to the `@src` directory
      app: [`scripts/main.js`, `styles/main.scss`],
      old: [`css/all.css`], // [`./sources/app.js`, `./sources/app.css`]

First I tell it that we’re using the postcss autoprefixer; then, I tell it what path to use to look for assets, include the images and fonts folders in the set of assets to copy over, tell it to minimize everything possible, and also add a hash for caching reasons. (Originally I wasn’t using that, but we were having problems with the admin staff not seeing things update immediately due to our caching solution, and that was easier than telling them how ctrl+shift+r works.)

Since I don’t have static filenames because of the hashing, I also have to add a little helper function on the php side:

function asset_path($filename) {
  $dist_path = get_template_directory_uri() . '/dist/';
  $directory = dirname($filename) . '/';
  $file = basename($filename);
  static $manifest;

  if (empty($manifest)) {
    $manifest_path = get_template_directory() . '/dist/' . 'assets.json';
    $manifest = new JsonManifest($manifest_path);

  if (array_key_exists($file, $manifest->get())) {
    return $dist_path . $directory . $manifest->get()[$file];
  } else {
    return $dist_path . $directory . $file;

This takes a filename, checks it against the manifest that bud.js generates, and then returns the actual full file path, presuming it exists, which makes sure you get the up-to-date version of the file every time.

The application entrypoints are the stylesheets and scripts that call a bunch of other stylesheets and scripts; in this case I’m compiling the newer scripts/main.js and styles/main.scss as well as a few old files that I hadn’t yet refactored, which get compiled separately under the old group.

The whole thing runs in a couple seconds on my M2 mac, compared to some of the older 30-second build processes I used to do and is just generally really snappy. I’ve never really understood webpack and find its documentation really opaque; the Bud.js docs leave a little to be desired when you’re trying to do something more unusual, but the fact that for most circumstances it configures right out of the box and just works is so nice.

other reads from my follows

Kudos With Cabin

I'm not one to really worry about page view metrics, but I do like to see which of my posts attract the most attention - and where that attention might be coming from. That insight has allowed me to find new blogs and sites that have linked to mine, a…

via runtimeterror June 24, 2024


A haiku

via Frills - Blog & experiments June 14, 2024

Animal dreams: a quote-o-dex

Animal dreams: a quote-o-dex Jun 13, 2024 I mentioned a while ago that I was reading a really absorbing book. It was Animal dreams, by Barbara Kingsolver. I actually finished it a while ago, maybe a week or so after I wrote that post, but it was so compelling…

via sorbier June 13, 2024

generated by openring