Releases: roots/bud
v6.5.3
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
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
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 appAPP_PUBLIC_PATH
- the public path for your appAPP_SRC_PATH
- the@src
path for your appAPP_DIST_PATH
- the@dist
path for your appAPP_STORAGE_PATH
- the@storage
path for your appAPP_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
Filesystem API, S3 uploads, and more.
⚠️ This release deprecates theoptIn
property and decorator for extensions. This doesn't matter unless you are authoring an extension. If you are, you can probably just usedependsOnOptional
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.
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.- The
bud.dashboard
service'sstats
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
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
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
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
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
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 ofpackage.json
- tip: set your compilation label using the
- 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
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
- 📦 deps: update @swc/core to v1.2.220 (#1610) [@swc-project]
- 📦 deps: update netlify-cli to v10.12.1 (#1612) [@netlify]
- 🩹 fix(patch): remove fn from allowed uris array (#1609) [@kellymears]
- 🩹 fix(patch): directory containing spaces (#1608) [@kellymears]
For more information review the diff to see what's changed.