Releases: roots/bud
6.13.1
A feature rich (and mostly backwards compatible) set of improvements and fixes for bud.js.
⚠️ Potentially breaking changes
single
runtimeChunk now enabled by default.- @roots/bud-eslint: warnings are not treated as errors by default.
- @roots/bud-eslint: errors will cause files to not emit in production.
- @roots/bud-stylelint: warnings are not treated as errors by default.
- @roots/bud-stylelint: errors will not emit in production.
- @roots/wordpress-theme-json-webpack-plugin: exported type
Theme
renamed toSchema
. - @roots/bud-terser: is replaced by @roots/bud-minify.
- you do not need to include this in your project; it is a transitive dependency of @roots/bud.
- bud.terser deprecated in favor of bud.minify.js
- bud.minimizeCss deprecated in favor of bud.minify.css
Core features
Enhanced support for tsconfig.json
You can now configure @src
, @dist
, compilation paths and aliases directly in tsconfig.json
. Also works with jsconfig.json
. This is nice for compatibility with the typescript compiler.
This feature is opt-in for now but will likely become a default in bud v7. To opt in set bud.useCompilerOptions
to true
in the config.
tsconfig key | value |
---|---|
compilerOptions.baseUrl |
Set @src directory |
compilerOptions.outDir |
Set @dist directory |
compilerOptions.paths |
Set bud path handles and aliases |
include |
Directories containing modules which should be treated as source. Same as calling bud.compilePaths |
Example annotated tsconfig.json
{
"extends": ["@roots/bud/config/tsconfig.json"],
"compilerOptions": {
/**
* Source directory
*
* @remarks
* This is the same as calling `bud.setPath(`@src`, `sources`)
*/
"baseUrl": “sources",
/**
* Output directory
*
* @remarks
* This is the same as calling `bud.setPath(`@dist`, `build`)
*/
"outDir": “build",
/**
* Path aliases
*
* @remarks
* This is the same as calling `bud.setPath()` and `bud.alias()`
* Only the first path in each value will be used.
*/
"paths": {
"@fonts": ["fonts"],
"@images": ["images"],
"@scripts": ["scripts"],
"@styles": ["styles"]
},
/**
* Include type definitions
*/
"types": [
"@roots/bud",
"@roots/bud-react",
"@roots/bud-postcss",
"webpack/module" // defines import.meta.webpackHot
]
},
/**
* Configuration files
*/
"files": ["bud.config.ts"],
/**
* Compiler paths
*
* @remarks
* This is the same as calling bud.compilePaths()
*/
"include": ["resources"],
/**
* Allow bud to reference tsconfig/jsconfig values
*/
"bud": {
"useCompilerOptions": true
}
}
TSC compatible module imports
With the TypeScript Compiler you can ensure your outputted code is compliant with esmodules by mapping extensions in your import statements. For example, if you want to import a module from ./some-module.ts
, you would likely want to import it like this:
import someModule from './some-module.js'
bud.js works the same way now, in practice. Now, if you want to write your import statements in a way that is compliant with TSC, you can.
bud.setPath
now automatically sets aliased paths
If you set a path handle with bud.setPath
it now sets up a path alias as well.
JSON schema available
JSON schema available at https://bud.js.org/bud.package.json
. You can optionally add it to package.json
for validation of package.json
fields (including bud specific ones):
{
"$schema": "https://bud.js.org/bud.package.json"
}
Improved extension options API
Every registered extension option now has a dedicated getter and setter. The getter prefixes the option key with get
and the setter prefixes it with set
.
Option | Getter | Setter |
---|---|---|
bud.extension.optionName | bud.extension.getOptionName() | bud.extension.setOptionName(value) |
Lastly, know that the setOptionName
always accepts a callback:
bud.extension.setOptionName(value => value)
Example
Let's say @roots/bud-eslint
has a new option defined (since it does):
lintDirtyModulesOnly: EslintPluginOptions['lintDirtyModulesOnly']
Previously you could get this value like so:
bud.eslint.get(`lintDirtyModulesOnly`)
That still works, but now you have some additional options:
/** Get the value via a property */
bud.eslint.lintDirtyModulesOnly
/** Get the value via a function */
bud.eslint.getLintDirtyModulesOnly()
Similarly, in addition to bud.eslint.set
:
bud.eslint.set(`lintDirtyModulesOnly`, true)
You can now set it with a dedicated setter method:
bud.eslint.setLintDirtyModulesOnly(true)
All such setter methods accept a callback:
bud.eslint.setLintDirtyModulesOnly(value => !value)
@roots/bud-postcss
- The postcss configuration API has gotten a rework.
Refer to the updated documentation for more information.
@roots/bud-eslint
- New options and methods exposed by
bud.eslint
- Configure eslint in your bud config
Refer to the updated documentation for more information.
@roots/bud-sass
- New options and methods exposed by
bud.sass
Refer to the updated documentation for more information.
@roots/bud-stylelint
- New options and methods exposed by
bud.stylelint
- Configure stylelint in your bud config
Refer to the updated documentation for more information.
@roots/bud-swc
- New options and methods exposed by
bud.swc
- Override base configuration for js and ts separately
Refer to the updated documentation for more information.
@roots/bud-tailwindcss
- New options and methods exposed by
bud.tailwind
- Supports configuring tailwindcss directly in bud config
Refer to the updated documentation for more information.
@roots/bud-wordpress-theme-json
- New options and methods exposed by
bud.wpjson
Other changes
experiments.backCompat
now set tofalse
. bud doesn't need backwards compatibility with webpack 4 and the compatibility fixes come with performance penalties related toArray
objects.snapshot.buildDependencies
uses a hash ifbud.env.get('CI')
istrue
; uses a timestamp otherwise.snapshot.module
uses a hash ifbud.env.get('CI')
istrue
; uses a timestamp otherwise.snapshot.resolve
uses a hash ifbud.env.get('CI')
istrue
; uses a timestamp otherwise.snapshot.resolveBuildDependencies
uses a hash ifbud.env.get('CI')
istrue
; uses a timestamp otherwise.resolveLoader.alias
defined for all registered loaders.resolve.unsafeCache
set toundefined
(wasfalse
). default behavior is forunsafeCache
to be used in development, and not used in production.profile
now set totrue
if--debug
flag istrue
.performance
now set tofalse
(was{hints: false}
).externalsType
set toundefined
(wasvar
).bud.context.logger
is removed.APP_TITLE
fallback set for projects which usebud.html
.NO_SCRIPT
fallback set for projects which usebud.html
.- Typings for WordPress
theme.json
updated using current schema. - Build script now in place to help with future updates to WordPress
theme.json
. - Default css minimizer is now lightningcss (css parser used by parcel).
- If using
@roots/bud-swc
css minification is handled by swc. - If using
@roots/bud-esbuild
css minification is handled by esbuild. - New documentation for bud.minify.
6.12.3
Bugfixes and bumped dependencies
Improvements
#2243 improves compatibility with pnpm
This change finishes work started in 6.12.2 make it less necessary to use the bud.js .pnpmfile.cjs compatibility shim.
You should also now be able to limit hoisting to @roots
packages, if desired:
pnpm install --public-hoist-pattern="@roots/*"
When only hoisting @roots/*
packages you will need to make sure your app dependencies are explicitly defined. Rule of thumb: if you import it in your app you will need to have it installed in your project.
The alternative is to hoist everything (same behavior as npm and yarn):
pnpm install --public-hoist-pattern="*"
Fixes
- Fixes module resolution cache validation when swapping package managers.
- Fixes issue with eslint not outputting to stdout/stderr in some configurations.
6.12.2
Adds cached module count to dashboard output for greater transparency into what is being recompiled in development.
6.12.1
Minor release with improvements and fixes for package resolution and caching
Fixes
Failure installing custom TypeScript version with yarn
Fixes an error encountered when trying to install a custom version of TypeScript while using @roots/bud-typescript
with yarn classic. See #2216.
This issue is actually an upstream bug in yarn. But, our response sidesteps it and also improves compatibility with pnpm.
The short version: we don't need to declare typescript
as a peer dependency because of changes to bud.module
made in bud v6. It will always try to resolve from the project context before using the built-in as a fallback.
So, even without peer dependencies defined by the extension, the following call (when made from the @roots/bud-typescript
context) will always try and resolve the module first from node_modules/typescript
, and then node_modules/@roots/bud-typescript/node_modules
.
bud.module.resolve(`typescript`, import.meta.url)
The change that fixes #2216 has also been applied to @roots/bud-eslint
and @roots/bud-babel
. We'll apply it to other packages which use peerDependencies
in future releases.
Improvements
Include eslint and tailwind configs in build dependencies
#2233 Include tailwind & eslint configs in cached build dependencies adds discovered tailwind
and eslint
configs to the map of files the compiler uses to validate the cache. Hopefully changes made to your tailwind config will now be more reliably reflected in your next build without having to use the --force
flag. Additionally, only modules related to the changed config will be invalidated, which will be much faster than wiping everything.
Prevent invoking multiple esbuild
and/or esbuild-wasm
modules
When transforming configuration modules authored in TypeScript bud.js will now prefer esbuild
or esbuild-wasm
as defined by package.json
, if they are included. The built-in esbuild-wasm
included in @roots/bud-support
is used as a fallback. This should be a minor improvement for users who are using esbuild
in some other way as part of their build.
Vendor bind
decorator from helpful-decorators
.
helpful-decorators
is an awesome package but we are only using bind
from it and it is used in a lot of places. This change eliminates the (modest) overhead associated with all the unused modules.
v6.12.0
Framework improvements, eslint fixes, better config
directory support, and more.
📦 tailwindcss 3.3.0 supported
bud.js now supports the new configuration options from tailwindcss 3.3.0. tailwind configs can now be authored with typescript or esm.
🧹 default storage location: .budfiles -> os cache dir
Less junk in your project is always good, right? The new default @storage
directory is now [os-cache dir]/bud-nodejs/[hash of project path]
.
Breaking change: If you are explicitly setting the @storage
directory you need to do it using the --storage
CLI flag or the APP_STORAGE_PATH
.env variable. By the time config files have been processed most reads and writes to @storage
will have already occurred, so bud.setPath
won't be effective. There will be a warning logged to the console if you are doing this; the main adverse effect will be slower builds when bud.js can't find caches during bootstrapping.
Potentially breaking change: If you are using remote modules (which lets you import modules from cdns like skypack without installing locally) the bud.lock
lockfile will now be written to the root of your project (unless you have configured it to be written somewhere else).
✨ Config files can be written in TypeScript (without extensions)
bud.js configuration files can now be authored in typescript without installing any additional extensions. if you were previously using the ts-bud
binary you still can (it executes the bud.js runtime with ts-node), but you can now just use the standard bud
command (it is faster). ts-bud
remains available in case you were doing some deeper integration with ts-node.
The parsing of TypeScript configs is handled with esbuild-wasm. I have not been able to measure a meaningful difference in timings using this package instead of esbuild and the wasm binary doesn't need to be built so installs are a lot faster. However, if you want to use esbuild instead of esbuild-wasm you can install esbuild as a project dependency and it will be used instead. Again, I don't think it's worth the extra installation time. Especially since the results of config transforms are cached.
This also applies to eslint, tailwindcss, postcss and babel configs.
✨ Config files can be stored in ./config
directory
bud.js configuration files can now be stored in the config
directory. This also applies to eslint, tailwindcss, postcss and babel configs.
✨ @roots/bud-eslint: upgrade eslint-webpack-plugin to v4
eslint-webpack-plugin@4 removes need for eslint cache fix
If you were disabling the fix with bud.eslint.cacheFix.enable(false)
before you will be prompted to remove that call, as it is now deprecated.
See #2191
🏎️ performance: module resolution caching
Module paths resolved by bud.module
are cached to [cachedir]/resolutions.yml
. This gives a nice performance boost since we can skip a lot of lookups:
The resolve
and import
methods used by bud.module
treat built-in dependencies as fallbacks. So, if you aren't overriding any built-in dependencies and the cache is valid the net result is more than half as many calls to importMetaResolve
and import
statements.
- sha1 hashes are calculated for files in root and
config/*
and an artifact is output to[cachedir]/checksum.yml
. - Hash mismatches in config files or
package.json
will invalidate thebud.module
resolver cache and thecompiler
cache.
🏎️ performance: reuse context & bud instances
bud.context
is now re-used between bootstrap scripts and the cli application.
✨ improve: unified error handling
Now extending modern-errors for unified error handling.
🩹 fix: no postinstall scripts in CI
There are some reliability issues with postinstall scripts (for @roots/bud-framework and @roots/browserslists-config) running in CI.
This update disables postinstall scripts when process.env.CI
is set (default for gh actions).
See #2169
✨ improve(@roots/eslint-config): remove react-in-jsx-scope
This rule is not really appropriate as a default for modern React.
See #2154
👩🔬 experimental: pnpm support
Installs with pnpm
should work now. They may break again in the future, but we're closer to being able to claim full compatibility. You must install with public hoisting:
pnpm install --public-hoist-pattern=*
pnpm installs peers by default as of pnpm v8 🎉, so we suspect that compatibility will be a lot better once people upgrade.
📦 upgrade ink to v4
A ton of workarounds were required to make ink work prior to this upgrade. It's now compatible with react 18 and fully esm 🎉.
📕 Documentation improvements
- Thanks to @chrillep for improving the
@roots/bud-eslint
documentation example config - Adds documentation for
bud.config
- Improves documentation for
bud.define
- Adds pnpm installation instructions to getting started guide
v6.11.0
A bunch of cool features, fixes and improvements.
If you have any trouble installing try the --force
flag.
Breaking changes
-
There have been some fixes made to bud.assets which make the function behave much more predictably. Still, I'm concerned there might be workarounds people are using which will no longer be working around. Check out the documentation and consider replacing complex bud.assets calls with the new bud.copyFile and bud.copyDir functions.
-
If you are configuring bud.js with JSON or YML you will need to update any functions which accept a single argument which is an array.
bud.config.json
andbud.config.yml
arguments are now expressed as an array, so there is no good way for the config parser to determine that you actually wanted to pass an array and not multiple params.assets: - - 'image.jpeg' + - ['image.jpeg']
-
If you have been using the new blade view directives in your Sage project you will need to update them. There is now a single directive to replace all previous directives:
@module
. So,@js import '@scripts/confetti.js' @endjs
becomes@module('js') import '@scripts/confetti.js' @endmodule
. This should support all module types now, generically. Built-in support for this feature is still in process for roots/acorn. An exampleModuleDirective
andEndModuleDirective
class have been updated and included in@roots/blade-loader/vendor
.-@js +@module('js') console.log('hello') -@endjs +@endmodule
Deprecations
A bunch of extension functions are going to be removed at some point in the future (bud.js 7). Most of these are simple wrappers for the built-in extensions API.
If you are using a deprecated function you can expect IDE notifications (if you use an IDE that supports the @deprecated
doctype), but you will also see warnings in the terminal with specific instructions for how to update the call.
We'll go slow when removing these functions; don't fret about it. This github issue (#2079) is dedicated to tracking related function deprecations.
Improved WordPress editor support
Easily add blocks
, plugins
, filters
, styles
, variations
and formats
in production and development with next to no boilerplate along with full hot module reloading (HMR) support.
See the updated documentation for specifics on implementing it in your WordPress project. There is also a new example in the examples directory to get a feel for how it comes together.
This feature is new so I suspect early adopters may bump into issues. But, we've been using the underlying library that powers this for many months now and it seems to work quite well in-house.
Improved yml and json config support
See the updated documentation. Short version: anything you can do in a js file you can now do in a yml file.
New functions for copying files
These two functions are a lot more predictable for you and will be a lot easier to maintain for me. I'd recommend replacing bud.assets with them (although I've tried to do what I can to improve it in this release).
bud.copyDir
See documentation for details.
bud.copyFile
See documentation for details.
Improved errors
There is better error handling in a few critical areas. Hopefully you'll never notice.
Early errors
Ever make a syntax error in your bud.config.js
file? Me neither. But if I did the error would happen before bud.js (and it's logger) had even been instantiated.
Not anymore!
Error reading config file:
bud.config.mjs appears to be a bud config file, but it could not be imported.
Original error follows:
SyntaxError: Unexpected token '}'
at file:///bud/sources/@roots/bud/lib/context/config.js:62:31
at async Promise.all (index 4)
bud.when errors
If you pass a non-function argument to bud.when it will throw an error now. I've seen a few people do this and it's an understandable mistake. I'm sorry for the error but it wasn't doing what you wanted before.
This is the specific mistake I saw most recently.
/* This will now throw */
bud.when(
bud.isProduction,
bud.minimize(), // oops!
)
The problem is that the function is being called right there! It's whatever value the function returns by the time bud.when
receives it. It doesn't cause a type error but it's obvious something is wrong.
The corrected version would just wrap the bud.minimize() call in an arrow function:
bud.when(
bud.isProduction,
() => bud.minimize() // corrected
)
Anyway, there will be instructions in the console if you are bit by this.
Unsupported platform errors
If you run bud.js on Windows outside of a WSL environment, it won't try and stop you, but it also won't work. This is mentioned in both the project README.md and our Getting Started guide, and yet many people still post support requests related to errors experienced while using Windows.
Now, errors are accompanied by a reminder that the platform is not supported, which should hopefully reduce support request volume.
If you use Windows and want to see native support for Windows in bud.js please submit an issue and accompanying PR!
Improve bud doctor
bud doctor
now displays additional information about the project and has a couple new checks.
Fix: sass/vue/sage (in combination)
Fixes an issue that could create blank stylesheets (with no error thrown from vue-loader
). Adds reproduction to prevent regressions.
Fix: @roots/bud-prettier format
command
Thanks to @nlemoine for fixing the bud format
command.
Docs contributions
Big thanks to @dsturm for their continued work improving bud.js' documentation 🙏🏼.
v6.9.1
v6.9.0
An easy helper for dealing with uncompiled modules, dot notation getters and setters for extension options, and a bugfix for the typescript+vue support introduced in 6.8.0
🩹 fix: vue/typescript #2082
Moves css
, scss
,ts
rules out of oneOf
and into the top-level module.rules
array.
Fixes:
- #2080 [bug] vue-typescript example does not build (possible @roots/bud-sass issue)
- #2081 [bug] Vue SFC ts breaks build
✨ feature(@roots/bud): bud.compilePaths #2083
bud.compilePaths is used to specify directories which should be treated as source directories. This serves as a simple replacement for the instructions found in the compiler sources guide.
If you have errors which say something along the lines of You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
, this is probably the function you want to use to fix that.
Example adding support for the swiper lib:
export default async bud => {
bud.compilePaths([
bud.path(`@src`),
bud.path(`@modules/swiper`),
])
}
✨ improve(@roots/bud): options api #2078
A small change but a good one. Backwards compatible but it will let us remove a lot of extension methods in bud@7.0.
export default async bud => {
bud.wpjson
.set(`settings.color.customDuotone`, false)
.set(`settings.color.customGradient`, false)
.set(`settings.color.defaultDuotone`, false)
.set(`settings.color.defaultGradients`, false)
.set(`settings.color.defaultPalette`, false)
.set(`settings.color.duotone`, [])
.enable()
bud.tailwind.set(`generateImports`, true)
bud.typescript
.set(`appendTsSuffixTo`, [/\.vue$/])
.typecheck.enable()
bud.terser
.set(`extractComments`, false)
.set(`terserOptions.mangle.safari10`, false)
bud.vue.set(`runtimeOnly`, false)
bud.imagemin.sharp
.set(`encodeOptions.png.quality`, 60)
.set(`encodeOptions.webp.quality`, 60)
}
Can also retrieve options with get
:
bud.vue.get(`runtimeOnly`)
Right now these dot props are not type safe and you may get feedback in your IDE that the option name doesn't exist. More work is roadmapped to address this, but it's very complicated to do dot notation type transformations on generics with recursive or very deeply nested properties.
If this is a problem for you you can do the prop drilling yourself with extension.getOptions()
and extension.setOptions()
.
v6.8.0
Bugfixes, host/container URL mappings and an improved cli experience.
🩹 fix(@roots/bud): remote sources #2057
Fixes issue with modules loaded from registered remote schemas.
🩹 fix(@roots/bud): resolve extensions #2058
Adds missing extensions to set of resolvable extensions.
🩹 fix(@roots/sage): blade loader caching #2065
Improves regular expression used to extract @asset
URLs and fixes caching for blade partials. Fixes issues referenced in this discourse topic.
✨ feature(@roots/bud): distinct settings for mapped URLs #2074
This is primarily targeted at docker users (including lando), or really anyone who has need for internal/external URLs for the proxy server, dev server, or both.
Adds the following methods:
bud.setProxyUrl
bud.setPublicProxyUrl
bud.setUrl
bud.setPublicUrl
Like bud.serve
and bud.proxy
they are pretty flexible and support strings, URL instances or numbers (if you only need to specify the port). If you only specify a port the default interface is used (0.0.0.0).
So, a lando user mapping 0.0.0.0
to example.lndo
can set it up like so:
export default async bud => {
bud
.setUrl(3000)
.setPublicUrl(`http://example.test:3000`)
.setProxyUrl(8000)
.setPublicProxyUrl(`http://example.test`)
}
This is especially useful for replacing URLs in proxy responses since the public URLs will be used for find/replace operations. The hope is that you won't have to handle these manually any longer.
This change should be backwards compatible with the existing bud.proxy and bud.serve functions. They can be used together and there is no plan on deprecating them:
export default async bud => {
bud
.proxy('http://0.0.0.0')
.setPublicProxyUrl('http://example.lndo')
.serve('http://0.0.0.0:3000')
.setPublicUrl('http://example.lndo:3000')
}
✨ feature(@roots/bud-vue): support typescript #2075
Adds automatic support for typescript in vue single file components. You only need to install @roots/bud-typescript and you should be good to go. Adds an example to the examples directory and integration tests to ensure this keeps working as the framework develops.
✨ feature(@roots/bud): improve bud cli #2004
Running bud
(no subcommand) presents user with menu of common tasks to select from. bud doctor
now displays additional information about the project.