Use "external" compilers in Bud

I made a sandbox that illustrate three ways of adding import-glob-loader to a project:

  • quick style: this is perfect for projects that want to quickly add a loader onto an existing rule. This is 3 lines of code!
  • polite style: this is how it should be done if you are authoring an extension in order to play nicely with the ecosystem
  • dirty style: this uses bud.webpackConfig to directly modify the normalized webpack config just before it is passed to the compiler. good if you know what you’re doing.

In the sandbox the “quick style” example is the one being run by default. If you want to try running the other two, fork the sandbox and adjust what calls are commented out.

Lastly, if you wanted to make an extension out of this I created a second sandbox that shows how to structure it as an extension. It’s 11 lines of code:

https://codesandbox.io/p/sandbox/import-glob-extension-1z8yhd?selection=[{"endColumn"%3A1%2C"endLineNumber"%3A12%2C"startColumn"%3A1%2C"startLineNumber"%3A12}]&file=%2Fimport-glob-extension.js

I don’t want to manage this extension because import-glob-loader was last published 8 years ago and I don’t want to be on the hook if it stops working. But, if someone else publishes it I’d promote your work.

2 Likes

Nice one, thanks @kellymears - been going about this in a pretty hacky way for sass + import-glob-loader.

  bud.hooks.on('build.module.rules.oneOf', (rules) => {
    const scssConfig = rules.splice(-1, 1)[0];

    scssConfig.use.push({
      loader: 'import-glob-loader',
    });

    rules.push(scssConfig);
    return rules;
  });

Haha pretty ugly! Dunno what I’m missing when I try it the “quick” way from your sandbox example. sass/scss isn’t a property when logging the bud.build.rules object? Guessing I’m missing something simple?

This is my bad. sass registers late – this was a design mistake on my part and something I’m improving so that this won’t be necessary.

This is where it gets registered:

configAfter extension methods are called on the config.after hook. As you might guess from the name this hook won’t be called until after the config is processed. But it’s already registered so we can override it:

export default async bud => bud.hooks.action(`config.after`, quick)

Here is a sandbox:

https://codesandbox.io/p/sandbox/import-glob-loader-forked-gdg5i0?selection=[{"endColumn"%3A1%2C"endLineNumber"%3A1%2C"startColumn"%3A1%2C"startLineNumber"%3A1}]&file=%2Fbud.config.mjs

In the sandbox I used build.before as the hook, which is the next hook after config.after, just to be really safe.

Soon, this won’t be a consideration. But, the hook code won’t break or anything once it’s improved, so it’s future-proof to include this workaround in your config.

1 Like

aha that’s much neater, thanks @kellymears appreciate it!

No problem!

Here is the PR for improving @roots/bud-sass:

No time like the present :yum:. This should be non-breaking so we can hopefully get it into a release soon.

One last thing – you may be able to do this without the import-glob-loader dependency:

export default async (bud) => {
  bud.sass.importGlobal(await bud.glob(`@src/styles/*.scss`));
};

This effectively prepends every stylesheet with @import statements created from the (resolvable) modules you pass it.

https://codesandbox.io/p/sandbox/import-glob-loader-forked-td53q5?selection=[{"endColumn"%3A1%2C"endLineNumber"%3A4%2C"startColumn"%3A1%2C"startLineNumber"%3A1}]&file=%2Fbud.config.mjs

2 Likes

Thank you so much, @kellymears. Tried it again without success a couple of days ago, but wasn’t aware of the late loading of the SASS extension. However that clarifies a lot and I am awaiting the next Bud release to hook in again.

There are some other packages around, which are more up-to-date. IMO this is very useful e.g. when working with styles for blocks separated into single files in /resources/styles/blocks/ directory. However I am not at the point with JS that I would take the ride. :slight_smile:

Cheers

An update on this:

I was doing some mad science (trying to compile bootstrap with only postcss). Failure, but I did end up trying this plugin which supports glob style imports:

Really nice experience!

1 Like