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.