This release contains backwards-incompatible changes. Since esbuild is before version 1.0.0, these changes have been released as a new minor version to reflect this (as recommended by npm). You should either be pinning the exact version of esbuild
in your package.json
file or be using a version range syntax that only accepts patch upgrades such as ^0.8.0
. See the documentation about semver for more information.
-
Add support for node's
exports
field inpackage.json
files (#187)This feature was recently added to node. It allows you to rewrite what import paths inside your package map to as well as to prevent people from importing certain files in your package. Adding support for this to esbuild is a breaking change (i.e. code that was working fine before can easily stop working) so adding support for it has been delayed until this breaking change release.
One way to use this feature is to remap import paths for your package. For example, this would remap an import of
your-pkg/esm/lib.js
(the "public" import path) toyour-pkg/dist/esm/lib.js
(the "private" file system path):{ "name": "your-pkg", "exports": { "./esm/*": "./dist/esm/*", "./cjs/*": "./dist/cjs/*" } }
Another way to use this feature is to have conditional imports where the same import path can mean different things in different situations. For example, this would remap
require('your-pkg')
toyour-pkg/required.cjs
andimport 'your-pkg'
toyour-pkg/imported.mjs
:{ "name": "your-pkg", "exports": { "import": "./imported.mjs", "require": "./required.cjs" } }
There is built-in support for the
import
andrequire
conditions depending on the kind of import and thebrowser
andnode
conditions depending on the current platform. In addition, thedefault
condition always applies regardless of the current configuration settings and can be used as a catch-all fallback condition.Note that when you use conditions, your package may end up in the bundle multiple times! This is a subtle issue that can cause bugs due to duplicate copies of your code's state in addition to bloating the resulting bundle. This is commonly known as the dual package hazard. The primary way of avoiding this is to put all of your code in the
require
condition and have theimport
condition just be a light wrapper that callsrequire
on your package and re-exports the package using ESM syntax.There is also support for custom conditions with the
--conditions=
flag. The meaning of these is entirely up to package authors. For example, you could imagine a package that requires you to configure--conditions=test,en-US
. Node has currently only endorsed thedevelopment
andproduction
custom conditions for recommended use. -
Remove the
esbuild.startService()
APIDue to #656, Calling
service.stop()
no longer does anything, so there is no longer a strong reason for keeping theesbuild.startService()
API around. The primary thing it currently does is just make the API more complicated and harder to use. You can now just callesbuild.build()
andesbuild.transform()
directly instead of callingesbuild.startService().then(service => service.build())
oresbuild.startService().then(service => service.transform())
.If you are using esbuild in the browser, you now need to call
esbuild.initialize({ wasmURL })
and wait for the returned promise before callingesbuild.transform()
. It takes the same options thatesbuild.startService()
used to take. Note that theesbuild.buildSync()
andesbuild.transformSync()
APIs still exist when using esbuild in node. Nothing has changed about the synchronous esbuild APIs. -
Remove the
metafile
fromoutputFiles
(#633)Previously using
metafile
with the API is unnecessarily cumbersome because you have to extract the JSON metadata from the output file yourself instead of it just being provided to you as a return value. This is especially a bummer if you are usingwrite: false
because then you need to use a for loop over the output files and do string comparisons with the file paths to try to find the one corresponding to themetafile
. Returning the metadata directly is an important UX improvement for the API. It means you can now do this:const result = await esbuild.build({ entryPoints: ['entry.js'], bundle: true, metafile: true, }) console.log(result.metafile.outputs)
-
The banner and footer options are now language-specific (#712)
The
--banner=
and--footer=
options now require you to pass the file type:-
CLI:
esbuild --banner:js=//banner --footer:js=//footer esbuild --banner:css=/*banner*/ --footer:css=/*footer*/
-
JavaScript
esbuild.build({ banner: { js: '//banner', css: '/*banner*/' }, footer: { js: '//footer', css: '/*footer*/' }, })
-
Go
api.Build(api.BuildOptions{ Banner: map[string]string{"js": "//banner"}, Footer: map[string]string{"js": "//footer"}, }) api.Build(api.BuildOptions{ Banner: map[string]string{"css": "/*banner*/"}, Footer: map[string]string{"css": "/*footer*/"}, })
This was changed because the feature was originally added in a JavaScript-specific manner, which was an oversight. CSS banners and footers must be separate from JavaScript banners and footers to avoid injecting JavaScript syntax into your CSS files.
-
-
The extensions
.mjs
and.cjs
are no longer implicitPreviously the "resolve extensions" setting included
.mjs
and.cjs
but this is no longer the case. This wasn't a good default because it doesn't match node's behavior and could break some packages. You now have to either explicitly specify these extensions or configure the "resolve extensions" setting yourself. -
Remove the
--summary
flag and instead just always print a summary (#704)The summary can be disabled if you don't want it by passing
--log-level=warning
instead. And it can be enabled in the API by settinglogLevel: 'info'
. I'm going to try this because I believe it will improve the UX. People have this problem with esbuild when they first try it where it runs so quickly that they think it must be broken, only to later discover that it actually worked fine. While this is funny, it seems like a good indication that the UX could be improved. So I'm going to try automatically printing a summary to see how that goes. Note that the summary is not printed if incremental builds are active (this includes the watch and serve modes). -
Rename
--error-limit=
to--log-limit=
This parameter has been renamed because it now applies to both warnings and errors, not just to errors. Previously setting the error limit did not apply any limits to the number of warnings printed, which could sometimes result in a deluge of warnings that are problematic for Windows Command Prompt, which is very slow to print to and has very limited scrollback. Now the log limit applies to the total number of log messages including both errors and warnings, so no more than that number of messages will be printed. The log usually prints log messages immediately but it will now intentionally hold back warnings when approaching the limit to make room for possible future errors during a build. So if a build fails you should be guaranteed to see an error message (i.e. warnings can't use up the entire log limit and then prevent errors from being printed).
-
Remove the deprecated
--avoid-tdz
optionThis option is now always enabled and cannot be disabled, so it is being removed from the API. The existing API parameter no longer does anything so this removal has no effect the generated output.
-
Remove
SpinnerBusy
andSpinnerIdle
from the Go APIThese options were part of an experiment with the CLI that didn't work out. Watch mode no longer uses a spinner because it turns out people want to be able to interleave esbuild's stderr pipe with other tools and were getting tripped up by the spinner animation. These options no longer do anything and have been removed.