Skip to main content

@roots/bud-postcss

PostCSS can be added by installing the @roots/bud-postcss extension.

Installation

yarn add @roots/bud-postcss --dev

Usage

By default, @roots/bud-postcss includes the following plugins, registered with postcss in this order:

OrderKeyPlugin
1.'import'postcss-import
2.'nesting'postcss-nested
3.'env'postcss-preset-env

If this works for you, great! No need to keep reading. But, should you need something more specialized, you can configure it in your bud config file or a postcss.config.js file in your project's root directory.

Any additional plugins you may want to add will be added between nesting and env. This is, generally, what you want, but there instructions included below for overriding this behavior.

Add a plugin

You can add a plugin with bud.postcss.setPlugin. This function takes up to two parameters.

The first parameter is required. It is the name for the plugin. If it is the only parameter being passed, it should be the module signifier.

bud.config.mjs
bud.postcss.setPlugin('example-postcss-plugin')

The second parameter is optional and multivariate.

Use a string to specify the plugin's resolvable path:

bud.config.mjs
bud.postcss.setPlugin(
'example-postcss-plugin',
bud.path('./directory/example.js'),
)

Use an array to set any associated options alongside the resolvable path.

bud.config.mjs
bud.postcss.setPlugin('example-postcss-plugin', [
bud.path('./directory/example.js'),
{stage: 1},
])

Override plugin options

You can modify options for a plugin using bud.postcss.setPluginOptions.

The first parameter is the plugin key and the second is the options object.

bud.config.mjs
bud.postcss.setPluginOptions('example-postcss-plugin', {optimize: false})

Override plugin resolution

You can modify the path for a postcss plugin using bud.postcss.setPluginPath.

The first parameter is the plugin key and the second is the new path to assign.

bud.config.mjs
bud.postcss.setPluginPath(
'example-postcss-plugin',
bud.path('./lib/my-plugin.js'),
)

Add multiple plugins

You can add multiple postcss plugins using bud.postcss.setPlugins.

Using an object

bud.config.mjs
bud.postcss.setPlugins({
['tailwindcss']: await bud.module.resolve('tailwindcss'),
['nesting']: await bud.module.resolve('tailwindcss/nesting/index.js'),
})

Using a Map

bud.config.mjs
bud.postcss.setPlugins(
new Map([])
.set('tailwindcss', await bud.module.resolve('tailwindcss'))
.set('nesting', [
await bud.module.resolve('tailwindcss/nesting/index.js'),
]),
)

Using an array

bud.config.mjs
bud.postcss.setPlugins([
['tailwindcss', await bud.module.resolve('tailwindcss')],
['nesting', await bud.module.resolve('tailwindcss/nesting/index.js')],
])

Remove a plugin

You may remove a plugin with bud.postcss.unsetPlugin.

bud.config.mjs
bud.postcss.unsetPlugin('import')

Plugin ordering

@roots/bud-postcss loosely attempts to enforce a particular plugin load order.

It will always attempt to load plugins in this order:

OrderDescriptionDefault
1import implementationpostcss-import
2nesting implementationpostcss-nested
...3all other plugins as registerednone
4env implementationpostcss-preset-env

The reason bud.js gets so hands-on here is to provide a reasonable default which people can build on without needing to splice in their own plugins manually. If this is a problem for your project, the most direct way to override this is to hook a function to postcss.plugins which returns an array of plugin values:

bud.config.mjs
bud.hooks.on('postcss.plugins', () => {
return [
bud.postcss.get('import'),
// ... plugins, in the order you wish to load them
]
})

Working with the plugin registry directly

@roots/bud-postcss stores PostCSS plugins as a Map. You can work with this Map directly using bud.postcss.plugins.

bud.config.mjs
bud.postcss.plugins.set('import', [
await module.resolve('postcss-import'),
{...options},
])

bud.postcss.plugins.get('import')

bud.postcss.plugins.delete('import')

bud.postcss.plugins.clear()

When you get something, you can hopefully rely on it being a tuple with the plugin in the first position and the options in the second. The plugin might be a string (resolveable path) or a module.