Skip to content

Releases: roots/bud

v6.5.3

24 Oct 01:06
Compare
Choose a tag to compare

Bug fix for @roots/bud-sass users.

Fix: early process exit on errors thrown from loaders, even in development

An error thrown by Sass in development mode would cause the process to exit early. This issue could effect other plugins, but it surfaced via reports by @roots/bud-sass users.

Regardless, the fix is general and should apply to all extensions.

ℹ️ Release information

For more information review the diff to see what's changed.

v6.5.2

23 Oct 00:03
Compare
Choose a tag to compare

Bugfix release for multi-instance configurations. Read on bud.js.org.

Fix: Client script injection TypeError when no entrypoints are specified

Specifying an entrypoint is optional and, accordingly, its value may very well return undefined. This possibility was not handled correctly by @roots/bud-server/inject for multi-instance configurations, and would throw a TypeError if a child didn't explicitly set an instance. This is now fixed.

Fix: Certain conditionally applied extensions enabled/disabled globally in multi-instance

In multi-instance configurations the last call to Extension.enable() or Extension.disable() would be applied to all instances. This has been fixed.

ℹ️ Release information

For more information review the diff to see what's changed.

v6.5.1

19 Oct 11:15
Compare
Choose a tag to compare

Read the release notes on bud.js.org.

Small fixes and improvements related to argv, package.json and .env settings.

🩹 Fix: argv parsing

These flags were janky but now they are golden:

  • --devtool - Set desired devtool
  • --clean - Enable or disable build cleaning
  • --discovery - Enable or disable automatic extension registration
  • --flush - Clean webpack cache

This release also adds a --runtime flag, which is new. It doesn't accept everything bud.runtime does, but you can use it to specify basic options like single or multiple.

✨ Improve: env context

You can now set certain values in your .env:

  • APP_BASE_PATH - the base path for your app
  • APP_PUBLIC_PATH - the public path for your app
  • APP_SRC_PATH - the @src path for your app
  • APP_DIST_PATH - the @dist path for your app
  • APP_STORAGE_PATH - the @storage path for your app
  • APP_MODE - desired build mode

✨ Improve: package.json context

The options available under the bud key in package.json have been expanded:

{
  "bud": {
    "paths": {
      "base": string,
      "src": string,
      "dist": string,
      "storage": string
    },
    "publicPath": string,
    "extensions": {
      "allowlist": string[],
      "denylist": string[],
      "discovery": boolean
    }
  }
}

If you are using bud.allowlist or bud.denylist, please update to bud.extensions.allowlist and bud.extensions.denylist. You'll get a warning in your terminal for now; in a future release this will cause an error.

🩹 Fix: SSL proxy rewrites and documentation

The implementation and documentation for the bud.serve function had fallen out-of-sync. The bud.serve documentation and development server configuration guides are now up-to-date.

Additionally, path rewrites for proxied URLs served over SSL were defaulting to 0.0.0.0 for hostname. This has been fixed.

Example of the config which served as a test case for this release:

.proxy("https://ssl-test.test")
.serve({
  host: "ssl-test.test",
  cert: `${process.env.HOME}/.config/valet/Certificates/ssl-test.test.crt`,
  key: `${process.env.HOME}/.config/valet/Certificates/ssl-test.test.key`,
})

To apply the hostname fix to earlier versions of bud you will need to apply the rewrite in your config:

// This is no longer necessary in 6.5.1
bud.proxy('https://ssl-test.test', [['0.0.0.0', 'ssl-test.test']])

ℹ️ Release information

For more information review the diff to see what's changed.

v6.5.0

14 Oct 21:21
Compare
Choose a tag to compare

Filesystem API, S3 uploads, and more.

⚠️ This release deprecates the optIn property and decorator for extensions. This doesn't matter unless you are authoring an extension. If you are, you can probably just use dependsOnOptional instead.

✨ bud.fs

bud.fs is a new filesystem API for bud.js. It uses fs-jetpack and includes support for managing s3 assets.

Example of a file write operation:

await bud.fs.write(`README.md`, `# Hello, world!`);

Example of the S3 API which uploads @dist contents to a bucket after compilation:

bud.fs
  .setCredentials({
    accessKeyId: `***`,
    secretAccessKey: `***`,
  })
  .setEndpoint(`https://sfo2.digitaloceanspaces.com`)
  .setBucket("bud-test")
  .upload();

Check the bud.fs docs for more information.

✨ bud.after

Config function for executing tasks after the compilation is fully complete. This is useful for tasks that need to run after the compilation is complete, but don't need to be part of the compilation process (like uploading assets to s3!)

export default async (bud) => {
  bud.after(async (bud) => {
    await bud.fs.write(
      `dist/credits.txt`,
      `${bud.context.manifest.name} built by me!`
    );
  });
};

Execute a command with bud.sh:

export default async (bud) => {
  bud.after(async (bud) => await bud.sh(`yarn jest`));
};

Check the bud.after docs for more information.

🩹 Fix: duplicative logs

Some logs would be displayed twice in the terminal if they were emitted around the same time that the dashboard was being updated.
It was also possible, depending on user configuration, for requests for the dashboard to update to fire twice. This has been fixed.

  1. console.* events are now caught by a new service: bud.bufferConsole. The service catches logs, trims and deduplicates them, and then emits them using an instance of the standard bud logger. If bud is invoked with the --ci flag the service will let them pass through normally.
  2. The bud.dashboard service's stats method is now debounced. Duplicative calls should be ignored.

It's likely that our handling of process.stdout is still imperfect, but this is a step in the right direction.

🩹 Fix: notifications only fire once (macos)

In dev mode only the first compilation would result in a desktop notification. This has been fixed. You should now receive a notification for every compilation.

🩹 Fix: bud.env is not an instance of Container

bud.env was not an instance of Container and therefore did not have methods like is. This has been fixed and it should now behave as documented.

🩹 Fix: dynamically imported chunks not hashed

Dynamically imported chunks were not being hashed. This has been fixed.

🩹 Fix: @roots/bud-criticalcss

A breaking change in the critical package had broken this extension. This change has now been accounted for and the extension should work again. This extension is still listed as experimental.

ℹ️ Release information

For more information review the diff to see what's changed.

v6.4.5

04 Oct 01:59
Compare
Choose a tag to compare

A bugfix release for bud 6.4.x. Read release notes on bud.js.org

@roots/bud-preset-wordpress: improve handling of WP_HOME

WP_HOME is now automatically set as a fallback proxy value. This means that if you don't call bud.proxy value in your bud.config.js file, the extension will attempt to use WP_HOME (if it is available and is a string value).

Previously, this value was set up front, which could cause errors if the value was malformed.

🩹 @roots/sage: bud.wpjson.useTailwindFontSize mutates config

This function no longer mutates the tailwind config. This caused tailwind to not generate css for font sizes.

@roots/sage: filter theme.json values to those used in theme.extend

If you wish to limit generated values in theme.json to those included in theme.extend, you can now do so with an optional parameter passed to useTailwindFontFamily, useTailwindColors, and useTailwindFontSize.

export default async bud => {
  /**
   * Limit generated values to those used in theme.extend
   */
  bud.wpjson.useTailwindFontFamily(true)
}

If called with no arguments, the default behavior is to generate all values resolved by tailwindcss.

⚠️ @roots/bud-tailwindcss: bud.tailwindcss.resolveTailwindThemeValue renamed to bud.tailwindcss.resolveThemeValue

This is an undocumented method but some of you may very well be using it. It's name changed.

🩹 fix: --browser flag not working

Regression introduced in 6.4.0. Fixed (with added unit tests).

ℹ️ Release information

For more information review the diff to see what's changed.

v6.4.4

28 Sep 10:27
Compare
Choose a tag to compare

A bugfix release for bud 6.4. Mainly focused on multi-instance configurations. Read on bud.js.org

🩹 fix: @roots/bud-postcss not applied in multi-instance configurations

Fixes an issue where @roots/bud-postcss was not applied to child compilations. (#1702).

📕 docs: improve multi-instance documentation

Added documentation for configuring development server in a multi-instance setup to the multi-instance guide. (#1713)

ℹ️ Release information

For more information review the diff to see what's changed.

v6.4.3

24 Sep 04:52
Compare
Choose a tag to compare

Release notes are also available on bud.js.org

🩹 fix: @roots/sage errors logged when not using tailwindcss

Errors no longer reported when not using tailwindcss in a @roots/sage project.

🩹 fix: @roots/sage bud.wpjson doesn't generate colors

Colors now generated for theme.json when using bud.wpjson.useTailwindColors()

✨ feature: @roots/bud-tailwindcss reference tailwindcss values in js files

You can now easily use tailwind theme values in your app code by importing them from the (virtual) @tailwind/* alias.

An example:

import {black} from '@tailwind/colors'
import {sans} from '@tailwind/fontFamily'

export const main = () => {
  document.body.style.backgroundColor = black
  document.body.style.fontFamily = sans
}

Generating the imports can be memory intensive and increase build times, so it is opt-in.

app.tailwind.generateImports()

Better to generate imports only for specific keys (much less memory intensive):

app.tailwind.generateImports([`colors`, `fontFamily`])

This is a lot better than trying to import the actual tailwind.config.js file to read these values as the values are fully resolved (merged with defaultTheme, plugins applied, etc.)

And it's a lot better than importing tailwindcss/resolveConfig and doing it in the app code because of the transitive dependencies taken on by that import.

It's also better than pre-compiling a static json file because these values are tree-shakeable. The entire generated json for the default tailwind config is ~100kb.

The above example adds ~5kb to the overall bundle (and only because tailwind has so many default colors). If you use terser (bud.minify) the difference is entirely negligible.

ℹ️ Release information

For more information review the diff to see what's changed.

v6.4.2

23 Sep 17:44
Compare
Choose a tag to compare

Release notes also available on bud.js.org

👉🏼 known issue: [@roots/sage] errors logged when not using tailwindcss

If you are not using @roots/bud-tailwindcss you will see errors in the logs when running bud build or bud dev.
This is a known issue and will be resolved in the next release. It isn't a sign that anything is wrong in your project.

✨ improve: [@roots/sage] bud.wpjson now fully resolves tailwind configs

Previously, bud.wpjson could only generate a theme.json based on a fully static tailwind config file. This excluded tailwind configs that
defined theme properties using functions and also meant that plugins would not be applied.

Now, bud.wpjson functions related to tailwindcss will fully resolve the tailwind config file and generate a theme.json based on the
processed config. This should mean that any tailwind config can be used in conjunction with bud.wpjson.useTailwindColors() and similar functions.

🩹 fix: build errors return non-zero exit code

For production builds, build errors will now result in a non-zero exit code. This regression was introduced in 6.4.0. It is now fixed.

🩹 fix: eslint.config.js support

eslint.config.js configurations are now supported.

🩹 fix: bud repl

The bud repl command has seen significant improvements since 6.4.0. It fixes a bug in 6.4.1 related to syntax highlighting.

ℹ️ Release information

For more information review the diff to see what's changed.

v6.4.0

20 Sep 23:11
Compare
Choose a tag to compare

Lots of fixes, features, and performance improvements. As always, you can read enhanced release notes at bud.js.org.

Client

hot reload middleware

Internally, bud.js has fully replaced webpack-hot-middleware and its associated client scripts.

What you can expect:

  • If you have an error in your code that fully breaks hot module reloading the client
    will automatically perform a full page reload.
  • You should have far fewer duplicate log messages about module updates.

proxy url replacement

If you are using bud.proxy you don't need to do anything. But, if you wanted to use this script directly it is now a lot more flexible.

There are two ways to utilize it:

1. add to your entry imports array

@roots/bud-client/lib/proxy-client-interceptor.js accepts URL parameters for search and replace strings.

bud.entry({
  app: [
    // ... app scripts and styles
    `@roots/bud-client/lib/proxy-client-interceptor.js?search=http://example.com&replace=/`,
  ],
})

2. import it in a client script

@roots/bud-client/lib/intercept.js can be imported directly and called from application code.

import intercept from '@roots/bud-client/lib/intercept.js'

intercept('http://example.com', '/')

improved: bud.config.local support

If you are on a team and team members have different needs for their local development environment, you can now use bud.config.local.mjs to override bud.config.mjs settings.

.local configs will always be applied after the base config.

improved: bud.assets

You can now specify copy options to apply to all copy patterns as a second parameter.

So the second parameter will be merged onto each pattern:

bud.assets(
  [
    {from: 'images', to: 'images'},
    {from: 'fonts', to: 'fonts'},
  ],
  {context: app.path('@assets')},
)

This is the same as:

bud.assets([
  {
    from: 'images',
    to: 'images',
    context: app.path('@assets'),
  },
  {
    from: 'fonts',
    to: 'fonts',
    context: app.path(`assets`),
  },
])

This also works with string or [from, to] tuples, as well.

new: bud.sh

bud.sh is a new config function that allows for executing arbitrary shell commands. It is a wrapper around the execa package.

It's async and returns the ExecaChildProcess object. It will pipe the process stdout/stderr to the console automatically.

await bud.sh('echo "hello world"')

Ideal for a hook like compiler.done, if you wanted to fire off a command when finalizing a build.

CLI

Enhanced build summary

Here's what you can expect:

◉  @tests/project ./dist [6c3fa82de0a7a70e5e45]
│
├─ entrypoints
│ ├─ app
│ │ └─ js/app.js           28.34 kB
│ ├─ app2
│ │ └─ js/app2.js          26.73 kB
│ └─ dev-client
│   └─ js/dev-client.js    84.61 kB
│
├─ assets
│ ├─ images/image.jpeg          761.41 kB
│ ├─ images/nested/image.jpeg   761.41 kB
│ └─ images/.gitkeep
│
└─ compiled 41 modules in 709ms

◉  HtmlWebpackCompiler ./dist [bce8eedbb4952eca25f3]
└─ compiled 6 modules in 262ms

ℹ server
╷
├─ internal: http://localhost:3015 (http://localhost:3015)
└─ external: http://192.168.194.103:3015 (http://192.168.194.103:3015)

… watching project sources

Some of the changes you may notice:

  • Displays information for multiple compilations.
  • Labeled (can be useful if running builds in parallel with yarn/npm workspaces).
    • tip: set your compilation label using the name field of package.json
  • Indicates the directory being emitted to (also handy for identification purposes).
  • Includes the oft-requested "external IP" for use over LAN.
  • Visually grouped by entrypoint
  • Improved display of compiler error messages
  • Improved display of compiler warning messages

bud repl

Start a repl to play around with bud: $ bud repl

option description default
--indent,-i indentation level 1
--depth,-d recursion depth 2

Some example queries you may wish to try:

  • $ bud.hooks.events.store
  • $ bud.extensions.get('webpack:define-plugin')
  • $ bud.make('test').then(bud => bud.get('test').label)
  • $ bud.extensions.make()
  • $ bud.hooks.filter('build.optimization')

bud view

Explore the bud object with $ yarn bud view. You can use dot notation to dive through properties.

option description default
--indent,-i indentation level 2
--color,-c color true

Interesting examples:

See what functions were called: $ yarn bud view api.trace

View the generated config: $ yarn bud view build.config

You can go as deep as you need but if you are accessing an array by index you'll probably need to escape the brackets with quotes:

$ yarn bud view 'build.config.module.rules[1].oneOf[0]'

bud webpack

This is a passthrough command for the webpack cli. Get webpack usage help $ yarn bud webpack -- --help

To run a build with webpack you'd probably want to create a new file named webpack.config.js in your project and do something like this:

// webpack.config.mjs

import {get} from '@roots/bud/factory'

export default async () => {
  const bud = await get()
  return await bud.build.make()
}

Run it with $ yarn bud webpack.

Flags

--basedir

Set the application base directory. Default: process.cwd()

--browser

Now accepts an (optional) string to open the project in a specific browser. The exact string is system dependent. Check the sindresorhus/open docs

--dry

Will run bud.js all the way up until it's time to actually instantiate the compiler or the dev server, and then it bails.

-v,-vv,-vvv,-vvvv

Set logging level.

Flag Level
-v error
-vv warning
-vvv log
-vvvv info (verbose)

default: -vv.

--debug

Emit artifacts to storage directory for debugging bud.js context or the emitted webpack configuration. In earlier versions of bud.js a snapshot of the finalized webpack configuration and a snapshot of bud.js state was always saved to storage prior to compilation. If your project is working correctly this is just needless fs overhead.

default: false

--reload

allow bud.js to hard reload the browser window when an error is encountered that breaks hot module reloading.

default: true

Extensions can register commands

Extensions can now register commands.

So far a few commands have been implemented:

  • yarn bud ts check will typecheck source assets (registered by @roots/bud-typescript).
  • yarn bud lint (alias: yarn bud eslint) will lint source assets (registered by @roots/bud-eslint).
  • yarn bud tailwindcss will transpile tailwindcss (registered by @roots/bud-tailwindcss).
  • yarn bud format (alias: yarn bud prettier) will format source assets (registered by @roots/bud-prettier).

Hooks

bud.hooks.fromMap

bud.hooks.fromMap can be used to set multiple hooks in one call.

bud.hooks.fromMap({
  'build.node': false,
  'build.resolve.extensions': ext => ext.add('.mjml'),
})

bud.hooks.fromAsyncMap

bud.hooks.fromAsyncMap can be used in the same way to set hooks with async callbacks.

bud.hooks.fromAsyncMap({
  'build.plugins': async () => await app.extensions.make(),
  'build.resolve.modules': async () => [
    app.hooks.filter(`location.@src`),
    app.hooks.filter(`location.@modules`),
  ],
})

Services

Services have access to some new methods that are called when the associated lifecycle event takes place.

In the order they are called:

method name associated lifecycle event
configAfter config.after
compileBefore compile.before
buildBefore build.before
buildAfter build.after
compileAfter compile.after

Extensions

Extensions have access to some new methods that are called when the associated lifecycle event takes place.

In the order they are called:

method name associated lifecycle event
configAfter config.after
buildBefore build.before
buildAfter build.after

✨ Improve: builds now labeled by package.json name field

In earlier versions of bud.js the bud.label property was always set to bud (for the parent compiler). Now, it will be set to the name field
of your project (as set in package.json). If you don't have a name set the new default is default.

In addition to the clearer output summary labeling (see above), you should also find that logs are better labeled now:

[bud@6.4.0] [my-project] › importing @roots/bud-terser/css-minimizer

ℹ️ Release information

For more information review the diff to see what's changed.

v6.3.5

28 Jul 21:13
Compare
Choose a tag to compare

Read the release notes on bud.js.org

🩹 Fix: resolved paths containing spaces

Paths resolved by bud.js's module resolve utility had spaces replaced with %20 in the path. This replacement was being made
by import-module-resolve's resolve function, which treats paths as browser-compatible URIs.

This small patch replaces %20 with (U+0020) before returning resolved paths.

ℹ️ Release information

For more information review the diff to see what's changed.