generated from nhcarrigan/template
deps: update esbuild to 0.27.2 #10
Open
minori
wants to merge 5 commits from
dependencies/update-esbuild into main
pull from: dependencies/update-esbuild
merge into: nhcarrigan:main
nhcarrigan:main
nhcarrigan:dependencies/update--swc-core
nhcarrigan:dependencies/update--nx-workspace
nhcarrigan:dependencies/update--nx-web
nhcarrigan:dependencies/update--nx-node
nhcarrigan:dependencies/update--nx-js
nhcarrigan:dependencies/update--nx-jest
nhcarrigan:dependencies/update--nx-eslint-plugin
nhcarrigan:dependencies/update--nx-eslint
nhcarrigan:dependencies/update--nx-esbuild
nhcarrigan:dependencies/update--nx-cypress
nhcarrigan:dependencies/update--nx-angular
nhcarrigan:dependencies/update--types-node
nhcarrigan:dependencies/update--fastify-jwt
nhcarrigan:dependencies/update-angular-eslint
nhcarrigan:dependencies/update-eslint-plugin-cypress
nhcarrigan:dependencies/update-prisma
nhcarrigan:dependencies/update--prisma-client
nhcarrigan:dependencies/update-fastify
nhcarrigan:dependencies/update--fastify-static
nhcarrigan:dependencies/update-ts-jest
nhcarrigan:dependencies/update--swc-helpers
nhcarrigan:dependencies/update-typescript
nhcarrigan:dependencies/update-jsdom
nhcarrigan:dependencies/update-jest-util
nhcarrigan:dependencies/update-jest-environment-node
nhcarrigan:dependencies/update-jest
nhcarrigan:dependencies/update-marked
nhcarrigan:dependencies/update-dompurify
nhcarrigan:dependencies/update-typescript-eslint
nhcarrigan:dependencies/update--typescript-eslint-utils
nhcarrigan:dependencies/update--types-jsdom
nhcarrigan:dependencies/update-nx
nhcarrigan:dependencies/update-eslint
nhcarrigan:dependencies/update--eslint-js
nhcarrigan:dependencies/update--schematics-angular
nhcarrigan:dependencies/update--angular-cli
nhcarrigan:dependencies/update--angular-devkit-schematics
nhcarrigan:dependencies/update--angular-devkit-core
nhcarrigan:dependencies/update--angular-devkit-build-angular
nhcarrigan:dependencies/update--angular-language-service
nhcarrigan:dependencies/update--angular-compiler-cli
nhcarrigan:dependencies/update--angular-router
nhcarrigan:dependencies/update--angular-platform-browser
nhcarrigan:dependencies/update--angular-forms
nhcarrigan:dependencies/update--angular-core
nhcarrigan:dependencies/update--angular-compiler
nhcarrigan:dependencies/update--angular-common
nhcarrigan:dependencies/update-cypress
nhcarrigan:dependencies/update-ts-node
nhcarrigan:dependencies/update--swc-node-register
nhcarrigan:dependencies/update-fastify-plugin
nhcarrigan:dependencies/update--fastify-cors
nhcarrigan:dependencies/update--fastify-autoload
No Reviewers
Labels
Clear labels
aspect
code
Concerns the software code in the repository
aspect
dx
Concerns developers' experience with the codebase
aspect
interface
Concerns end-users' experience with the software
aspect
text
Concerns the documentation material in the repository
contribute
good first issue
A great opportunity for a team member to learn a new codebase
contribute
help wanted
Open for anyone on our team to grab.
contribute
staff only
Restricted to our executive leadership.
goal
addition
Addition of new feature
goal
fix
Bug fix
goal
improvement
Improvement to an existing feature
points
1
Very simple issue requiring minimal effort and complexity.
points
13
Extremely complex issue representing major undertakings. Should be broken down into smaller pieces.
points
2
Simple issue that requires a bit more thought or investigation.
points
3
Moderate complexity issue requiring more substantial work.
points
5
Complex issue requiring significant effort and expertise.
points
8
Very complex issue requiring extensive work and deep expertise.
priority
critical
1
Must be fixed ASAP
priority
high
2
Stalls work on the project or its dependents
priority
low
4
Low priority and doesn't need to be rushed
priority
medium
3
Not blocking but should be fixed soon
priority
none
5
No priority, should only be performed when a developer is available
status
awaiting triage
Has not been triaged & therefore, not ready for work
status
blocked
Blocked and therefore not ready for work
status
discarded
Will not be worked on
status
discontinued
Not suitable for work as repo is in maintenance
status
label work required
Needs proper labelling before it can be worked on
status
ready for dev
Ready for work
status
ticket work required
Needs more details before it can be worked on
talk
discussion
Open for discussions and feedback
talk
question
Can be resolved with an answer
time
1 day
Approximately one full day of development work.
time
1-2 weeks
One to two weeks of focused development effort.
time
2-3 days
Two to three days of development effort.
time
4-5 days
Approximately one week of development work.
time
<1 day
Less than one day of focused work. Quick fixes or simple tasks.
time
>2 weeks
More than two weeks of development work. Must be broken down into smaller pieces.
No Label
Milestone
No items
No Milestone
Assignees
gurkirat
hanna (Hanna Rose)
hikari (Hikari)
minori (Minori)
naomi (Naomi Carrigan)
rain
teklu
tim
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: nhcarrigan/library#10
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "dependencies/update-esbuild"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Dependency Update
Updates esbuild from
0.19.12to0.27.2.Type
devDependencies
Changelog
Changelog
v0.27.2
Allow import path specifiers starting with
#/(#4361)Previously the specification for
package.jsondisallowed import path specifiers starting with#/, but this restriction has recently been relaxed and support for it is being added across the JavaScript ecosystem. One use case is using it for a wildcard pattern such as mapping#/*to./src/*(previously you had to use another character such as#_*instead, which was more confusing). There is some more context in nodejs/node#49182.This change was contributed by @hybrist.
Automatically add the
-webkit-maskprefix (#4357, #4358)This release automatically adds the
-webkit-vendor prefix for themaskCSS shorthand property:This change was contributed by @BPJEnnova.
Additional minification of
switchstatements (#4176, #4359)This release contains additional minification patterns for reducing
switchstatements. Here is an example:Forbid
usingdeclarations insideswitchclauses (#4323)This is a rare change to remove something that was previously possible. The Explicit Resource Management proposal introduced
usingdeclarations. These were previously allowed insidecaseanddefaultclauses inswitchstatements. This had well-defined semantics and was already widely implemented (by V8, SpiderMonkey, TypeScript, esbuild, and others). However, it was considered to be too confusing because of how scope works in switch statements, so it has been removed from the specification. This edge case will now be a syntax error. See tc39/proposal-explicit-resource-management#215 and rbuckton/ecma262#14 for details.Here is an example of code that is no longer allowed:
That code will now have to be modified to look like this instead (note the additional
{and}block statements around each case body):This is not being released in one of esbuild's breaking change releases since this feature hasn't been finalized yet, and esbuild always tracks the current state of the specification (so esbuild's previous behavior was arguably incorrect).
v0.27.1
Fix bundler bug with
varnested insideif(#4348)This release fixes a bug with the bundler that happens when importing an ES module using
require(which causes it to be wrapped) and there's a top-levelvarinside anifstatement without being wrapped in a{ ... }block (and a few other conditions). The bundling transform needed to hoist thesevardeclarations outside of the lazy ES module wrapper for correctness. See the issue for details.Fix minifier bug with
forinsidetryinside label (#4351)This fixes an old regression from version v0.21.4. Some code was introduced to move the label inside the
trystatement to address a problem with transforming labeledfor awaitloops to avoid theawait(the transformation involves converting thefor awaitloop into aforloop and wrapping it in atrystatement). However, it introduces problems for cross-compiled JVM code that uses all three of these features heavily. This release restricts this transform to only apply toforloops that esbuild itself generates internally as part of thefor awaittransform. Here is an example of some affected code:Inline IIFEs containing a single expression (#4354)
Previously inlining of IIFEs (immediately-invoked function expressions) only worked if the body contained a single
returnstatement. Now it should also work if the body contains a single expression statement instead:The minifier now strips empty
finallyclauses (#4353)This improvement means that
finallyclauses containing dead code can potentially cause the associatedtrystatement to be removed from the output entirely in minified builds:Allow tree-shaking of the
SymbolconstructorWith this release, calling
Symbolis now considered to be side-effect free when the argument is known to be a primitive value. This means esbuild can now tree-shake module-level symbol variables:v0.27.0
This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of
esbuildin yourpackage.jsonfile (recommended) or be using a version range syntax that only accepts patch upgrades such as^0.26.0or~0.26.0. See npm's documentation about semver for more information.Use
Uint8Array.fromBase64if available (#4286)With this release, esbuild's
binaryloader will now use the newUint8Array.fromBase64function unless it's unavailable in the configured target environment. If it's unavailable, esbuild's previous code for this will be used as a fallback. Note that this means you may now need to specifytargetwhen using this feature with Node (for example--target=node22) unless you're using Node v25+.Update the Go compiler from v1.23.12 to v1.25.4 (#4208, #4311)
This raises the operating system requirements for running esbuild:
v0.26.0
Enable trusted publishing (#4281)
GitHub and npm are recommending that maintainers for packages such as esbuild switch to trusted publishing. With this release, a VM on GitHub will now build and publish all of esbuild's packages to npm instead of me. In theory.
Unfortunately there isn't really a way to test that this works other than to do it live. So this release is that live test. Hopefully this release is uneventful and is exactly the same as the previous one (well, except for the green provenance attestation checkmark on npm that happens with trusted publishing).
v0.25.12
Fix a minification regression with CSS media queries (#4315)
The previous release introduced support for parsing media queries which unintentionally introduced a regression with the removal of duplicate media rules during minification. Specifically the grammar for
@media <media-type> and <media-condition-without-or> { ... }was missing an equality check for the<media-condition-without-or>part, so rules with different suffix clauses in this position would incorrectly compare equal and be deduplicated. This release fixes the regression.Update the list of known JavaScript globals (#4310)
This release updates esbuild's internal list of known JavaScript globals. These are globals that are known to not have side-effects when the property is accessed. For example, accessing the global
Arrayproperty is considered to be side-effect free but accessing the globalscrollYproperty can trigger a layout, which is a side-effect. This is used by esbuild's tree-shaking to safely remove unused code that is known to be side-effect free. This update adds the following global properties:From ES2017:
AtomicsSharedArrayBufferFrom ES2020:
BigInt64ArrayBigUint64ArrayFrom ES2021:
FinalizationRegistryWeakRefFrom ES2025:
Float16ArrayIteratorNote that this does not indicate that constructing any of these objects is side-effect free, just that accessing the identifier is side-effect free. For example, this now allows esbuild to tree-shake classes that extend from
Iterator:Add support for the new
@view-transitionCSS rule (#4313)With this release, esbuild now has improved support for pretty-printing and minifying the new
@view-transitionrule (which esbuild was previously unaware of):The new view transition feature provides a mechanism for creating animated transitions between documents in a multi-page app. You can read more about view transition rules here.
This change was contributed by @yisibl.
Trim CSS rules that will never match
The CSS minifier will now remove rules whose selectors contain
:is()and:where()as those selectors will never match. These selectors can currently be automatically generated by esbuild when you give esbuild nonsensical input such as the following:This input is nonsensical because CSS nesting is (unfortunately) not supported inside of pseudo-elements such as
:before. Currently esbuild generates a rule containing:is()in this case when you tell esbuild to transform nested CSS into non-nested CSS. I think it's reasonable to do that as it sort of helps explain what's going on (or at least indicates that something is wrong in the output). It shouldn't be present in minified code, however, so this release now strips it out.v0.25.11
Add support for
with { type: 'bytes' }imports (#4292)The import bytes proposal has reached stage 2.7 in the TC39 process, which means that although it isn't quite recommended for implementation, it's generally approved and ready for validation. Furthermore it has already been implemented by Deno and Webpack. So with this release, esbuild will also add support for this. It behaves exactly the same as esbuild's existing
binaryloader. Here's an example:Lower CSS media query range syntax (#3748, #4293)
With this release, esbuild will now transform CSS media query range syntax into equivalent syntax using
min-/max-prefixes for older browsers. For example, the following CSS:will be transformed like this with a target such as
--target=chrome100(or more specifically with--supported:media-range=falseif desired):v0.25.10
Fix a panic in a minification edge case (#4287)
This release fixes a panic due to a null pointer that could happen when esbuild inlines a doubly-nested identity function and the final result is empty. It was fixed by emitting the value
undefinedin this case, which avoids the panic. This case must be rare since it hasn't come up until now. Here is an example of code that previously triggered the panic (which only happened when minifying):Fix
@supportsnested inside pseudo-element (#4265)When transforming nested CSS to non-nested CSS, esbuild is supposed to filter out pseudo-elements such as
::placeholderfor correctness. The CSS nesting specification says the following:However, it seems like this behavior is different for nested at-rules such as
@supports, which do work with pseudo-elements. So this release modifies esbuild's behavior to now take that into account:v0.25.9
Better support building projects that use Yarn on Windows (#3131, #3663)
With this release, you can now use esbuild to bundle projects that use Yarn Plug'n'Play on Windows on drives other than the
C:drive. The problem was as follows:C:driveD:drive../..to get from the project directory to the cache directory..(soD:\..is justD:)Yarn works around this edge case by pretending Windows-style paths beginning with
C:\are actually Unix-style paths beginning with/C:/, so the../..path segments are able to navigate across drives inside Yarn's implementation. This was broken for a long time in esbuild but I finally got access to a Windows machine and was able to debug and fix this edge case. So you should now be able to bundle these projects with esbuild.Preserve parentheses around function expressions (#4252)
The V8 JavaScript VM uses parentheses around function expressions as an optimization hint to immediately compile the function. Otherwise the function would be lazily-compiled, which has additional overhead if that function is always called immediately as lazy compilation involves parsing the function twice. You can read V8's blog post about this for more details.
Previously esbuild did not represent parentheses around functions in the AST so they were lost during compilation. With this change, esbuild will now preserve parentheses around function expressions when they are present in the original source code. This means these optimization hints will not be lost when bundling with esbuild. In addition, esbuild will now automatically add this optimization hint to immediately-invoked function expressions. Here's an example:
Note that you do not want to wrap all function expressions in parentheses. This optimization hint should only be used for functions that are called on initial load. Using this hint for functions that are not called on initial load will unnecessarily delay the initial load. Again, see V8's blog post linked above for details.
Update Go from 1.23.10 to 1.23.12 (#4257, #4258)
This should have no effect on existing code as this version change does not change Go's operating system support. It may remove certain false positive reports (specifically CVE-2025-4674 and CVE-2025-47907) from vulnerability scanners that only detect which version of the Go compiler esbuild uses.
v0.25.8
Fix another TypeScript parsing edge case (#4248)
This fixes a regression with a change in the previous release that tries to more accurately parse TypeScript arrow functions inside the
?:operator. The regression specifically involves parsing an arrow function containing a#privateidentifier inside the middle of a?:ternary operator inside a class body. This was fixed by propagating private identifier state into the parser clone used to speculatively parse the arrow function body. Here is an example of some affected code:Fix a regression with the parsing of source phase imports
The change in the previous release to parse source phase imports failed to properly handle the following cases:
Parsing for these cases should now be fixed. The first case was incorrectly treated as a syntax error because esbuild was expecting the second case. And the last case was previously allowed but is now forbidden. TypeScript hasn't added this feature yet so it remains to be seen whether the last case will be allowed, but it's safer to disallow it for now. At least Babel doesn't allow the last case when parsing TypeScript, and Babel was involved with the source phase import specification.
v0.25.7
Parse and print JavaScript imports with an explicit phase (#4238)
This release adds basic syntax support for the
deferandsourceimport phases in JavaScript:deferThis is a stage 3 proposal for an upcoming JavaScript feature that will provide one way to eagerly load but lazily initialize imported modules. The imported module is automatically initialized on first use. Support for this syntax will also be part of the upcoming release of TypeScript 5.9. The syntax looks like this:
Note that this feature deliberately cannot be used with the syntax
import defer foo from "<specifier>"orimport defer { foo } from "<specifier>".sourceThis is a stage 3 proposal for an upcoming JavaScript feature that will provide another way to eagerly load but lazily initialize imported modules. The imported module is returned in an uninitialized state. Support for this syntax may or may not be a part of TypeScript 5.9 (see this issue for details). The syntax looks like this:
Note that this feature deliberately cannot be used with the syntax
import defer * as foo from "<specifier>"orimport defer { foo } from "<specifier>".This change only adds support for this syntax. These imports cannot currently be bundled by esbuild. To use these new features with esbuild's bundler, the imported paths must be external to the bundle and the output format must be set to
esm.Support optionally emitting absolute paths instead of relative paths (#338, #2082, #3023)
This release introduces the
--abs-paths=feature which takes a comma-separated list of situations where esbuild should use absolute paths instead of relative paths. There are currently three supported situations:code(comments and string literals),log(log message text and location info), andmetafile(the JSON build metadata).Using absolute paths instead of relative paths is not the default behavior because it means that the build results are no longer machine-independent (which means builds are no longer reproducible). Absolute paths can be useful when used with certain terminal emulators that allow you to click on absolute paths in the terminal text and/or when esbuild is being automatically invoked from several different directories within the same script.
Fix a TypeScript parsing edge case (#4241)
This release fixes an edge case with parsing an arrow function in TypeScript with a return type that's in the middle of a
?:ternary operator. For example:The
:token in the value assigned toxpairs with the?token, so it's not the start of a return type annotation. However, the first:token in the value assigned toyis the start of a return type annotation because after parsing the arrow function body, it turns out there's another:token that can be used to pair with the?token. This case is notable as it's the first TypeScript edge case that esbuild has needed a backtracking parser to parse. It has been addressed by a quick hack (cloning the whole parser) as it's a rare edge case and esbuild doesn't otherwise need a backtracking parser. Hopefully this is sufficient and doesn't cause any issues.Inline small constant strings when minifying
Previously esbuild's minifier didn't inline string constants because strings can be arbitrarily long, and this isn't necessarily a size win if the string is used more than once. Starting with this release, esbuild will now inline string constants when the length of the string is three code units or less. For example:
Note that esbuild's constant inlining only happens in very restrictive scenarios to avoid issues with TDZ handling. This change doesn't change when esbuild's constant inlining happens. It only expands the scope of it to include certain string literals in addition to numeric and boolean literals.
v0.25.6
Fix a memory leak when
cancel()is used on a build context (#4231)Calling
rebuild()followed bycancel()in rapid succession could previously leak memory. The bundler uses a producer/consumer model internally, and the resource leak was caused by the consumer being termianted while there were still remaining unreceived results from a producer. To avoid the leak, the consumer now waits for all producers to finish before terminating.Support empty
:is()and:where()syntax in CSS (#4232)Previously using these selectors with esbuild would generate a warning. That warning has been removed in this release for these cases.
Improve tree-shaking of
trystatements in dead code (#4224)With this release, esbuild will now remove certain
trystatements if esbuild considers them to be within dead code (i.e. code that is known to not ever be evaluated). For example:Consider negated bigints to have no side effects
While esbuild currently considers
1,-1, and1nto all have no side effects, it didn't previously consider-1nto have no side effects. This is because esbuild does constant folding with numbers but not bigints. However, it meant that unused negative bigint constants were not tree-shaken. With this release, esbuild will now consider these expressions to also be side-effect free:Support a configurable delay in watch mode before rebuilding (#3476, #4178)
The
watch()API now takes adelayoption that lets you add a delay (in milliseconds) before rebuilding when a change is detected in watch mode. If you use a tool that regenerates multiple source files very slowly, this should make it more likely that esbuild's watch mode won't generate a broken intermediate build before the successful final build. This option is also available via the CLI using the--watch-delay=flag.This should also help avoid confusion about the
watch()API's options argument. It was previously empty to allow for future API expansion, which caused some people to think that the documentation was missing. It's no longer empty now that thewatch()API has an option.Allow mixed array for
entryPointsAPI option (#4223)The TypeScript type definitions now allow you to pass a mixed array of both string literals and object literals to the
entryPointsAPI option, such as['foo.js', { out: 'lib', in: 'bar.js' }]. This was always possible to do in JavaScript but the TypeScript type definitions were previously too restrictive.Update Go from 1.23.8 to 1.23.10 (#4204, #4207)
This should have no effect on existing code as this version change does not change Go's operating system support. It may remove certain false positive reports (specifically CVE-2025-4673 and CVE-2025-22874) from vulnerability scanners that only detect which version of the Go compiler esbuild uses.
Experimental support for esbuild on OpenHarmony (#4212)
With this release, esbuild now publishes the
@esbuild/openharmony-arm64npm package for OpenHarmony. It contains a WebAssembly binary instead of a native binary because Go doesn't currently support OpenHarmony. Node does support it, however, so in theory esbuild should now work on OpenHarmony through WebAssembly.This change was contributed by @hqzing.
v0.25.5
Fix a regression with
browserinpackage.json(#4187)The fix to #4144 in version 0.25.3 introduced a regression that caused
browseroverrides specified inpackage.jsonto fail to override relative path names that end in a trailing slash. That behavior change affected theaxios@0.30.0package. This regression has been fixed, and now has test coverage.Add support for certain keywords as TypeScript tuple labels (#4192)
Previously esbuild could incorrectly fail to parse certain keywords as TypeScript tuple labels that are parsed by the official TypeScript compiler if they were followed by a
?modifier. These labels includedfunction,import,infer,new,readonly, andtypeof. With this release, these keywords will now be parsed correctly. Here's an example of some affected code:Add CSS prefixes for the
stretchsizing value (#4184)This release adds support for prefixing CSS declarations such as
div { width: stretch }. That CSS is now transformed into this depending on what the--target=setting includes:v0.25.4
Add simple support for CORS to esbuild's development server (#4125)
Starting with version 0.25.0, esbuild's development server is no longer configured to serve cross-origin requests. This was a deliberate change to prevent any website you visit from accessing your running esbuild development server. However, this change prevented (by design) certain use cases such as "debugging in production" by having your production website load code from
localhostwhere the esbuild development server is running.To enable this use case, esbuild is adding a feature to allow Cross-Origin Resource Sharing (a.k.a. CORS) for simple requests. Specifically, passing your origin to the new
corsoption will now set theAccess-Control-Allow-Originresponse header when the request has a matchingOriginheader. Note that this currently only works for requests that don't send a preflightOPTIONSrequest, as esbuild's development server doesn't currently supportOPTIONSrequests.Some examples:
CLI:
JS:
Go:
The special origin
*can be used to allow any origin to access esbuild's development server. Note that this means any website you visit will be able to read everything served by esbuild.Pass through invalid URLs in source maps unmodified (#4169)
This fixes a regression in version 0.25.0 where
sourcesin source maps that form invalid URLs were not being passed through to the output. Version 0.25.0 changed the interpretation ofsourcesfrom file paths to URLs, which means that URL parsing can now fail. Previously URLs that couldn't be parsed were replaced with the empty string. With this release, invalid URLs insourcesshould now be passed through unmodified.Handle exports named
__proto__in ES modules (#4162, #4163)In JavaScript, the special property name
__proto__sets the prototype when used inside an object literal. Previously esbuild's ESM-to-CommonJS conversion didn't special-case the property name of exports named__proto__so the exported getter accidentally became the prototype of the object literal. It's unclear what this affects, if anything, but it's better practice to avoid this by using a computed property name in this case.This fix was contributed by @magic-akari.
v0.25.3
Fix lowered
asyncarrow functions beforesuper()(#4141, #4142)This change makes it possible to call an
asyncarrow function in a constructor before callingsuper()when targeting environments withoutasyncsupport, as long as the function body doesn't referencethis. Here's an example (notice the change fromthistonull):Some background: Arrow functions with the
asynckeyword are transformed into generator functions for older language targets such as--target=es2016. Since arrow functions capturethis, the generated code forwardsthisinto the body of the generator function. However, JavaScript class syntax forbids usingthisin a constructor before callingsuper(), and this forwarding was problematic since previously happened even when the function body doesn't usethis. Starting with this release, esbuild will now only forwardthisif it's used within the function body.This fix was contributed by @magic-akari.
Fix memory leak with
--watch=true(#4131, #4132)This release fixes a memory leak with esbuild when
--watch=trueis used instead of--watch. Previously using--watch=truecaused esbuild to continue to use more and more memory for every rebuild, but--watch=trueshould now behave like--watchand not leak memory.This bug happened because esbuild disables the garbage collector when it's not run as a long-lived process for extra speed, but esbuild's checks for which arguments cause esbuild to be a long-lived process weren't updated for the new
--watch=truestyle of boolean command-line flags. This has been an issue since this boolean flag syntax was added in version 0.14.24 in 2022. These checks are unfortunately separate from the regular argument parser because of how esbuild's internals are organized (the command-line interface is exposed as a separate Go API so you can build your own custom esbuild CLI).This fix was contributed by @mxschmitt.
More concise output for repeated legal comments (#4139)
Some libraries have many files and also use the same legal comment text in all files. Previously esbuild would copy each legal comment to the output file. Starting with this release, legal comments duplicated across separate files will now be grouped in the output file by unique comment content.
Allow a custom host with the development server (#4110)
With this release, you can now use a custom non-IP
hostwith esbuild's local development server (either with--serve=for the CLI or with theserve()call for the API). This was previously possible, but was intentionally broken in version 0.25.0 to fix a security issue. This change adds the functionality back except that it's now opt-in and only for a single domain name that you provide.For example, if you add a mapping in your
/etc/hostsfile fromlocal.example.comto127.0.0.1and then useesbuild --serve=local.example.com:8000, you will now be able to visit http://local.example.com:8000/ in your browser and successfully connect to esbuild's development server (doing that would previously have been blocked by the browser). This should also work with HTTPS if it's enabled (see esbuild's documentation for how to do that).Add a limit to CSS nesting expansion (#4114)
With this release, esbuild will now fail with an error if there is too much CSS nesting expansion. This can happen when nested CSS is converted to CSS without nesting for older browsers as expanding CSS nesting is inherently exponential due to the resulting combinatorial explosion. The expansion limit is currently hard-coded and cannot be changed, but is extremely unlikely to trigger for real code. It exists to prevent esbuild from using too much time and/or memory. Here's an example:
Previously, transforming this file with
--target=safari1took 5 seconds and generated 40mb of CSS. Trying to do that will now generate the following error instead:Fix path resolution edge case (#4144)
This fixes an edge case where esbuild's path resolution algorithm could deviate from node's path resolution algorithm. It involves a confusing situation where a directory shares the same file name as a file (but without the file extension). See the linked issue for specific details. This appears to be a case where esbuild is correctly following node's published resolution algorithm but where node itself is doing something different. Specifically the step
LOAD_AS_FILEappears to be skipped when the input ends with... This release changes esbuild's behavior for this edge case to match node's behavior.Update Go from 1.23.7 to 1.23.8 (#4133, #4134)
This should have no effect on existing code as this version change does not change Go's operating system support. It may remove certain reports from vulnerability scanners that detect which version of the Go compiler esbuild uses, such as for CVE-2025-22871.
As a reminder, esbuild's development server is intended for development, not for production, so I do not consider most networking-related vulnerabilities in Go to be vulnerabilities in esbuild. Please do not use esbuild's development server in production.
v0.25.2
Support flags in regular expressions for the API (#4121)
The JavaScript plugin API for esbuild takes JavaScript regular expression objects for the
filteroption. Internally these are translated into Go regular expressions. However, this translation previously ignored theflagsproperty of the regular expression. With this release, esbuild will now translate JavaScript regular expression flags into Go regular expression flags. Specifically the JavaScript regular expression/\.[jt]sx?$/iis turned into the Go regular expression`(?i)\.[jt]sx?$`internally inside of esbuild's API. This should make it possible to use JavaScript regular expressions with theiflag. Note that JavaScript and Go don't support all of the same regular expression features, so this mapping is only approximate.Fix node-specific annotations for string literal export names (#4100)
When node instantiates a CommonJS module, it scans the AST to look for names to expose via ESM named exports. This is a heuristic that looks for certain patterns such as
exports.NAME = ...ormodule.exports = { ... }. This behavior is used by esbuild to "annotate" CommonJS code that was converted from ESM with the original ESM export names. For example, when converting the fileexport let foo, barfrom ESM to CommonJS, esbuild appends this to the end of the file:However, this feature previously didn't work correctly for export names that are not valid identifiers, which can be constructed using string literal export names. The generated code contained a syntax error. That problem is fixed in this release:
Basic support for index source maps (#3439, #4109)
The source map specification has an optional mode called index source maps that makes it easier for tools to create an aggregate JavaScript file by concatenating many smaller JavaScript files with source maps, and then generate an aggregate source map by simply providing the original source maps along with some offset information. My understanding is that this is rarely used in practice. I'm only aware of two uses of it in the wild: ClojureScript and Turbopack.
This release provides basic support for indexed source maps. However, the implementation has not been tested on a real app (just on very simple test input). If you are using index source maps in a real app, please try this out and report back if anything isn't working for you.
Note that this is also not a complete implementation. For example, index source maps technically allows nesting source maps to an arbitrary depth, while esbuild's implementation in this release only supports a single level of nesting. It's unclear whether supporting more than one level of nesting is important or not given the lack of available test cases.
This feature was contributed by @clyfish.
v0.25.1
Fix incorrect paths in inline source maps (#4070, #4075, #4105)
This fixes a regression from version 0.25.0 where esbuild didn't correctly resolve relative paths contained within source maps in inline
sourceMappingURLdata URLs. The paths were incorrectly being passed through as-is instead of being resolved relative to the source file containing thesourceMappingURLcomment, which was due to the data URL not being a file URL. This regression has been fixed, and this case now has test coverage.Fix invalid generated source maps (#4080, #4082, #4104, #4107)
This release fixes a regression from version 0.24.1 that could cause esbuild to generate invalid source maps. Specifically under certain conditions, esbuild could generate a mapping with an out-of-bounds source index. It was introduced by code that attempted to improve esbuild's handling of "null" entries in source maps (i.e. mappings with a generated position but no original position). This regression has been fixed.
This fix was contributed by @jridgewell.
Fix a regression with non-file source map paths (#4078)
The format of paths in source maps that aren't in the
filenamespace was unintentionally changed in version 0.25.0. Path namespaces is an esbuild-specific concept that is optionally available for plugins to use to distinguish paths fromfilepaths and from paths meant for other plugins. Previously the namespace was prepended to the path joined with a:character, but version 0.25.0 unintentionally failed to prepend the namespace. The previous behavior has been restored.Fix a crash with
switchoptimization (#4088)The new code in the previous release to optimize dead code in switch statements accidentally introduced a crash in the edge case where one or more switch case values include a function expression. This is because esbuild now visits the case values first to determine whether any cases are dead code, and then visits the case bodies once the dead code status is known. That triggered some internal asserts that guard against traversing the AST in an unexpected order. This crash has been fixed by changing esbuild to expect the new traversal ordering. Here's an example of affected code:
Update Go from 1.23.5 to 1.23.7 (#4076, #4077)
This should have no effect on existing code as this version change does not change Go's operating system support. It may remove certain reports from vulnerability scanners that detect which version of the Go compiler esbuild uses.
This PR was contributed by @MikeWillCook.
v0.25.0
This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of
esbuildin yourpackage.jsonfile (recommended) or be using a version range syntax that only accepts patch upgrades such as^0.24.0or~0.24.0. See npm's documentation about semver for more information.Restrict access to esbuild's development server (GHSA-67mh-4wv8-2f99)
This change addresses esbuild's first security vulnerability report. Previously esbuild set the
Access-Control-Allow-Originheader to*to allow esbuild's development server to be flexible in how it's used for development. However, this allows the websites you visit to make HTTP requests to esbuild's local development server, which gives read-only access to your source code if the website were to fetch your source code's specific URL. You can read more information in the report.Starting with this release, CORS will now be disabled, and requests will now be denied if the host does not match the one provided to
--serve=. The default host is0.0.0.0, which refers to all of the IP addresses that represent the local machine (e.g. both127.0.0.1and192.168.0.1). If you want to customize anything about esbuild's development server, you can put a proxy in front of esbuild and modify the incoming and/or outgoing requests.In addition, the
serve()API call has been changed to return an array ofhostsinstead of a singlehoststring. This makes it possible to determine all of the hosts that esbuild's development server will accept.Thanks to @sapphi-red for reporting this issue.
Delete output files when a build fails in watch mode (#3643)
It has been requested for esbuild to delete files when a build fails in watch mode. Previously esbuild left the old files in place, which could cause people to not immediately realize that the most recent build failed. With this release, esbuild will now delete all output files if a rebuild fails. Fixing the build error and triggering another rebuild will restore all output files again.
Fix correctness issues with the CSS nesting transform (#3620, #3877, #3933, #3997, #4005, #4037, #4038)
This release fixes the following problems:
Naive expansion of CSS nesting can result in an exponential blow-up of generated CSS if each nesting level has multiple selectors. Previously esbuild sometimes collapsed individual nesting levels using
:is()to limit expansion. However, this collapsing wasn't correct in some cases, so it has been removed to fix correctness issues.Thanks to @tim-we for working on a fix.
The
&CSS nesting selector can be repeated multiple times to increase CSS specificity. Previously esbuild ignored this possibility and incorrectly considered&&to have the same specificity as&. With this release, this should now work correctly:Thanks to @CPunisher for working on a fix.
Previously transforming nested CSS incorrectly removed leading combinators from within pseudoclass selectors such as
:where(). This edge case has been fixed and how has test coverage.This fix was contributed by @NoremacNergfol.
The CSS minifier contains logic to remove the
&selector when it can be implied, which happens when there is only one and it's the leading token. However, this logic was incorrectly also applied to selector lists inside of pseudo-class selectors such as:where(). With this release, the minifier will now avoid applying this logic in this edge case:Fix some correctness issues with source maps (#1745, #3183, #3613, #3982)
Previously esbuild incorrectly treated source map path references as file paths instead of as URLs. With this release, esbuild will now treat source map path references as URLs. This fixes the following problems with source maps:
File names in
sourceMappingURLthat contained a space previously did not encode the space as%20, which resulted in JavaScript tools (including esbuild) failing to read that path back in when consuming the generated output file. This should now be fixed.Absolute URLs in
sourceMappingURLthat use thefile://scheme previously attempted to read from a folder calledfile:. These URLs should now be recognized and parsed correctly.Entries in the
sourcesarray in the source map are now treated as URLs instead of file paths. The correct behavior for this is much more clear now that source maps has a formal specification. Many thanks to those who worked on the specification.Fix incorrect package for
@esbuild/netbsd-arm64(#4018)Due to a copy+paste typo, the binary published to
@esbuild/netbsd-arm64was not actually forarm64, and didn't run in that environment. This release should fix running esbuild in that environment (NetBSD on 64-bit ARM). Sorry about the mistake.Fix a minification bug with bitwise operators and bigints (#4065)
This change removes an incorrect assumption in esbuild that all bitwise operators result in a numeric integer. That assumption was correct up until the introduction of bigints in ES2020, but is no longer correct because almost all bitwise operators now operate on both numbers and bigints. Here's an example of the incorrect minification:
Fix esbuild incorrectly rejecting valid TypeScript edge case (#4027)
The following TypeScript code is valid:
Before this version, esbuild would fail to parse this with a syntax error as it expected the token sequence
async as ...to be the start of an async arrow function expressionasync as => .... This edge case should be parsed correctly by esbuild starting with this release.Transform BigInt values into constructor calls when unsupported (#4049)
Previously esbuild would refuse to compile the BigInt literals (such as
123n) if they are unsupported in the configured target environment (such as with--target=es6). The rationale was that they cannot be polyfilled effectively because they change the behavior of JavaScript's arithmetic operators and JavaScript doesn't have operator overloading.However, this prevents using esbuild with certain libraries that would otherwise work if BigInt literals were ignored, such as with old versions of the
bufferlibrary before the library fixed support for running in environments without BigInt support. So with this release, esbuild will now turn BigInt literals into BigInt constructor calls (so123nbecomesBigInt(123)) and generate a warning in this case. You can turn off the warning with--log-override:bigint=silentor restore the warning to an error with--log-override:bigint=errorif needed.Change how
consoleAPI dropping works (#4020)Previously the
--drop:consolefeature replaced all method calls off of theconsoleglobal withundefinedregardless of how long the property access chain was (so it applied toconsole.log()andconsole.log.call(console)andconsole.log.not.a.method()). However, it was pointed out that this breaks uses ofconsole.log.bind(console). That's also incompatible with Terser's implementation of the feature, which is where this feature originally came from (it does supportbind). So with this release, using this feature with esbuild will now only replace one level of method call (unless extended bycallorapply) and will replace the method being called with an empty function in complex cases:This should more closely match Terser's existing behavior.
Allow BigInt literals as
definevaluesWith this release, you can now use BigInt literals as define values, such as with
--define:FOO=123n. Previously trying to do this resulted in a syntax error.Fix a bug with resolve extensions in
node_modules(#4053)The
--resolve-extensions=option lets you specify the order in which to try resolving implicit file extensions. For complicated reasons, esbuild reorders TypeScript file extensions after JavaScript ones inside ofnode_modulesso that JavaScript source code is always preferred to TypeScript source code inside of dependencies. However, this reordering had a bug that could accidentally change the relative order of TypeScript file extensions if one of them was a prefix of the other. That bug has been fixed in this release. You can see the issue for details.Better minification of statically-determined
switchcases (#4028)With this release, esbuild will now try to trim unused code within
switchstatements when the test expression andcaseexpressions are primitive literals. This can arise when the test expression is an identifier that is substituted for a primitive literal at compile time. For example:Emit
/* @__KEY__ */for string literals derived from property names (#4034)Property name mangling is an advanced feature that shortens certain property names for better minification (I say "advanced feature" because it's very easy to break your code with it). Sometimes you need to store a property name in a string, such as
obj.get('foo')instead ofobj.foo. JavaScript minifiers such as esbuild and Terser have a convention where a/* @__KEY__ */comment before the string makes it behave like a property name. Soobj.get(/* @__KEY__ */ 'foo')allows the contents of the string'foo'to be shortened.However, esbuild sometimes itself generates string literals containing property names when transforming code, such as when lowering class fields to ES6 or when transforming TypeScript decorators. Previously esbuild didn't generate its own
/* @__KEY__ */comments in this case, which means that minifying your code by running esbuild again on its own output wouldn't work correctly (this does not affect people that both minify and transform their code in a single step).With this release, esbuild will now generate
/* @__KEY__ */comments for property names in generated string literals. To avoid lots of unnecessary output for people that don't use this advanced feature, the generated comments will only be present when the feature is active. If you want to generate the comments but not actually mangle any property names, you can use a flag that has no effect such as--reserve-props=., which tells esbuild to not mangle any property names (but still activates this feature).The
textloader now strips the UTF-8 BOM if present (#3935)Some software (such as Notepad on Windows) can create text files that start with the three bytes
0xEF 0xBB 0xBF, which is referred to as the "byte order mark". This prefix is intended to be removed before using the text. Previously esbuild'stextloader included this byte sequence in the string, which turns into a prefix of\uFEFFin a JavaScript string when decoded from UTF-8. With this release, esbuild'stextloader will now remove these bytes when they occur at the start of the file.Omit legal comment output files when empty (#3670)
Previously configuring esbuild with
--legal-comment=externalor--legal-comment=linkedwould always generate a.LEGAL.txtoutput file even if it was empty. Starting with this release, esbuild will now only do this if the file will be non-empty. This should result in a more organized output directory in some cases.Update Go from 1.23.1 to 1.23.5 (#4056, #4057)
This should have no effect on existing code as this version change does not change Go's operating system support. It may remove certain reports from vulnerability scanners that detect which version of the Go compiler esbuild uses.
This PR was contributed by @MikeWillCook.
Allow passing a port of 0 to the development server (#3692)
Unix sockets interpret a port of 0 to mean "pick a random unused port in the ephemeral port range". However, esbuild's default behavior when the port is not specified is to pick the first unused port starting from 8000 and upward. This is more convenient because port 8000 is typically free, so you can for example restart the development server and reload your app in the browser without needing to change the port in the URL. Since esbuild is written in Go (which does not have optional fields like JavaScript), not specifying the port in Go means it defaults to 0, so previously passing a port of 0 to esbuild caused port 8000 to be picked.
Starting with this release, passing a port of 0 to esbuild when using the CLI or the JS API will now pass port 0 to the OS, which will pick a random ephemeral port. To make this possible, the
Portoption in the Go API has been changed fromuint16toint(to allow for additional sentinel values) and passing a port of -1 in Go now picks a random port. Both the CLI and JS APIs now remap an explicitly-provided port of 0 into -1 for the internal Go API.Another option would have been to change
Portin Go fromuint16to*uint16(Go's closest equivalent ofnumber | undefined). However, that would make the common case of providing an explicit port in Go very awkward as Go doesn't support taking the address of integer constants. This tradeoff isn't worth it as picking a random ephemeral port is a rare use case. So the CLI and JS APIs should now match standard Unix behavior when the port is 0, but you need to use -1 instead with Go API.Minification now avoids inlining constants with direct
eval(#4055)Direct
evalcan be used to introduce a new variable like this:Previously esbuild inlined
variablehere (which becamefalse), which changed the behavior of the code. This inlining is now avoided, but please keep in mind that directevalbreaks many assumptions that JavaScript tools hold about normal code (especially when bundling) and I do not recommend using it. There are usually better alternatives that have a more localized impact on your code. You can read more about this here: https://esbuild.github.io/link/direct-eval/v0.24.2
Fix regression with
--defineandimport.meta(#4010, #4012, #4013)The previous change in version 0.24.1 to use a more expression-like parser for
definevalues to allow quoted property names introduced a regression that removed the ability to use--define:import.meta=.... Even thoughimportis normally a keyword that can't be used as an identifier, ES modules special-case theimport.metaexpression to behave like an identifier anyway. This change fixes the regression.This fix was contributed by @sapphi-red.
v0.24.1
Allow
es2024as a target intsconfig.json(#4004)TypeScript recently added
es2024as a compilation target, so esbuild now supports this in thetargetfield oftsconfig.jsonfiles, such as in the following configuration file:As a reminder, the only thing that esbuild uses this field for is determining whether or not to use legacy TypeScript behavior for class fields. You can read more in the documentation.
This fix was contributed by @billyjanitsch.
Allow automatic semicolon insertion after
get/setThis change fixes a grammar bug in the parser that incorrectly treated the following code as a syntax error:
The above code will be considered valid starting with this release. This change to esbuild follows a similar change to TypeScript which will allow this syntax starting with TypeScript 5.7.
Allow quoted property names in
--defineand--pure(#4008)The
defineandpureAPI options now accept identifier expressions containing quoted property names. Previously all identifiers in the identifier expression had to be bare identifiers. This change now makes--defineand--pureconsistent with--global-name, which already supported quoted property names. For example, the following is now possible:Note that if you're passing values like this on the command line using esbuild's
--defineflag, then you'll need to know how to escape quote characters for your shell. You may find esbuild's JavaScript API more ergonomic and portable than writing shell code.Minify empty
try/catch/finallyblocks (#4003)With this release, esbuild will now attempt to minify empty
tryblocks:This can sometimes expose additional minification opportunities.
Include
entryPointmetadata for thecopyloader (#3985)Almost all entry points already include a
entryPointfield in theoutputsmap in esbuild's build metadata. However, this wasn't the case for thecopyloader as that loader is a special-case that doesn't behave like other loaders. This release adds theentryPointfield in this case.Source mappings may now contain
nullentries (#3310, #3878)With this change, sources that result in an empty source map may now emit a
nullsource mapping (i.e. one with a generated position but without a source index or original position). This change improves source map accuracy by fixing a problem where minified code from a source without any source mappings could potentially still be associated with a mapping from another source file earlier in the generated output on the same minified line. It manifests as nonsensical files in source mapped stack traces. Now thenullmapping "resets" the source map so that any lookups into the minified code without any mappings resolves tonull(which appears as the output file in stack traces) instead of the incorrect source file.This change shouldn't affect anything in most situations. I'm only mentioning it in the release notes in case it introduces a bug with source mapping. It's part of a work-in-progress future feature that will let you omit certain unimportant files from the generated source map to reduce source map size.
Avoid using the parent directory name for determinism (#3998)
To make generated code more readable, esbuild includes the name of the source file when generating certain variable names within the file. Specifically bundling a CommonJS file generates a variable to store the lazily-evaluated module initializer. However, if a file is named
index.js(or with a different extension), esbuild will use the name of the parent directory instead for a better name (since many packages have files all namedindex.jsbut have unique directory names).This is problematic when the bundle entry point is named
index.jsand the parent directory name is non-deterministic (e.g. a temporary directory created by a build script). To avoid non-determinism in esbuild's output, esbuild will now useindexinstead of the parent directory in this case. Specifically this will happen if the parent directory is equal to esbuild'soutbaseAPI option, which defaults to the lowest common ancestor of all user-specified entry point paths.Experimental support for esbuild on NetBSD (#3974)
With this release, esbuild now has a published binary executable for NetBSD in the
@esbuild/netbsd-arm64npm package, and esbuild's installer has been modified to attempt to use it when on NetBSD. Hopefully this makes installing esbuild via npm work on NetBSD. This change was contributed by @bsiegert.⚠️ Note: NetBSD is not one of Node's supported platforms, so installing esbuild may or may not work on NetBSD depending on how Node has been patched. This is not a problem with esbuild. ⚠️
v0.24.0
This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of
esbuildin yourpackage.jsonfile (recommended) or be using a version range syntax that only accepts patch upgrades such as^0.23.0or~0.23.0. See npm's documentation about semver for more information.Drop support for older platforms (#3902)
This release drops support for the following operating system:
This is because the Go programming language dropped support for this operating system version in Go 1.23, and this release updates esbuild from Go 1.22 to Go 1.23. Go 1.23 now requires macOS 11 Big Sur or later.
Note that this only affects the binary esbuild executables that are published to the esbuild npm package. It's still possible to compile esbuild's source code for these older operating systems. If you need to, you can compile esbuild for yourself using an older version of the Go compiler (before Go version 1.23). That might look something like this:
Fix class field decorators in TypeScript if
useDefineForClassFieldsisfalse(#3913)Setting the
useDefineForClassFieldsflag tofalseintsconfig.jsonmeans class fields use the legacy TypeScript behavior instead of the standard JavaScript behavior. Specifically they use assign semantics instead of define semantics (e.g. setters are triggered) and fields without an initializer are not initialized at all. However, when this legacy behavior is combined with standard JavaScript decorators, TypeScript switches to always initializing all fields, even those without initializers. Previously esbuild incorrectly continued to omit field initializers for this edge case. These field initializers in this case should now be emitted starting with this release.Avoid incorrect cycle warning with
tsconfig.jsonmultiple inheritance (#3898)TypeScript 5.0 introduced multiple inheritance for
tsconfig.jsonfiles whereextendscan be an array of file paths. Previously esbuild would incorrectly treat files encountered more than once when processing separate subtrees of the multiple inheritance hierarchy as an inheritance cycle. With this release,tsconfig.jsonfiles containing this edge case should work correctly without generating a warning.Handle Yarn Plug'n'Play stack overflow with
tsconfig.json(#3915)Previously a
tsconfig.jsonfile thatextendsanother file in a package with anexportsmap could cause a stack overflow when Yarn's Plug'n'Play resolution was active. This edge case should work now starting with this release.Work around more issues with Deno 1.31+ (#3917)
This version of Deno broke the
stdinandstdoutproperties on command objects for inherited streams, which matters when you run esbuild's Deno module as the entry point (i.e. whenimport.meta.mainistrue). Previously esbuild would crash in Deno 1.31+ if you ran esbuild like that. This should be fixed starting with this release.This fix was contributed by @Joshix-1.
v0.23.1
Allow using the
node:import prefix withes*targets (#3821)The
node:prefix on imports is an alternate way to import built-in node modules. For example,import fs from "fs"can also be writtenimport fs from "node:fs". This only works with certain newer versions of node, so esbuild removes it when you target older versions of node such as with--target=node14so that your code still works. With the way esbuild's platform-specific feature compatibility table works, this was added by saying that only newer versions of node support this feature. However, that means that a target such as--target=node18,es2022removes thenode:prefix because none of thees*targets are known to support this feature. This release adds the support for thenode:flag to esbuild's internal compatibility table fores*to allow you to use compound targets like this:Fix a panic when using the CLI with invalid build flags if
--analyzeis present (#3834)Previously esbuild's CLI could crash if it was invoked with flags that aren't valid for a "build" API call and the
--analyzeflag is present. This was caused by esbuild's internals attempting to add a Go plugin (which is how--analyzeis implemented) to a null build object. The panic has been fixed in this release.Fix incorrect location of certain error messages (#3845)
This release fixes a regression that caused certain errors relating to variable declarations to be reported at an incorrect location. The regression was introduced in version 0.18.7 of esbuild.
Print comments before case clauses in switch statements (#3838)
With this release, esbuild will attempt to print comments that come before case clauses in switch statements. This is similar to what esbuild already does for comments inside of certain types of expressions. Note that these types of comments are not printed if minification is enabled (specifically whitespace minification).
Fix a memory leak with
pluginData(#3825)With this release, the build context's internal
pluginDatacache will now be cleared when starting a new build. This should fix a leak of memory from plugins that returnpluginDataobjects fromonResolveand/oronLoadcallbacks.v0.23.0
This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of
esbuildin yourpackage.jsonfile (recommended) or be using a version range syntax that only accepts patch upgrades such as^0.22.0or~0.22.0. See npm's documentation about semver for more information.Revert the recent change to avoid bundling dependencies for node (#3819)
This release reverts the recent change in version 0.22.0 that made
--packages=externalthe default behavior with--platform=node. The default is now back to--packages=bundle.I've just been made aware that Amazon doesn't pin their dependencies in their "AWS CDK" product, which means that whenever esbuild publishes a new release, many people (potentially everyone?) using their SDK around the world instantly starts using it without Amazon checking that it works first. This change in version 0.22.0 happened to break their SDK. I'm amazed that things haven't broken before this point. This revert attempts to avoid these problems for Amazon's customers. Hopefully Amazon will pin their dependencies in the future.
In addition, this is probably a sign that esbuild is used widely enough that it now needs to switch to a more complicated release model. I may have esbuild use a beta channel model for further development.
Fix preserving collapsed JSX whitespace (#3818)
When transformed, certain whitespace inside JSX elements is ignored completely if it collapses to an empty string. However, the whitespace should only be ignored if the JSX is being transformed, not if it's being preserved. This release fixes a bug where esbuild was previously incorrectly ignoring collapsed whitespace with
--jsx=preserve. Here is an example:v0.22.0
This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of
esbuildin yourpackage.jsonfile (recommended) or be using a version range syntax that only accepts patch upgrades such as^0.21.0or~0.21.0. See npm's documentation about semver for more information.Omit packages from bundles by default when targeting node (#1874, #2830, #2846, #2915, #3145, #3294, #3323, #3582, #3809, #3815)
This breaking change is an experiment. People are commonly confused when using esbuild to bundle code for node (i.e. for
--platform=node) because some packages may not be intended for bundlers, and may use node-specific features that don't work with a bundler. Even though esbuild's "getting started" instructions say to use--packages=externalto work around this problem, many people don't read the documentation and don't do this, and are then confused when it doesn't work. So arguably this is a bad default behavior for esbuild to have if people keep tripping over this.With this release, esbuild will now omit packages from the bundle by default when the platform is
node(i.e. the previous behavior of--packages=externalis now the default in this case). Note that your dependencies must now be present on the file system when your bundle is run. If you don't want this behavior, you can do--packages=bundleto allow packages to be included in the bundle (i.e. the previous default behavior). Note that--packages=bundledoesn't mean all packages are bundled, just that packages are allowed to be bundled. You can still exclude individual packages from the bundle using--external:even when--packages=bundleis present.The
--packages=setting considers all import paths that "look like" package imports in the original source code to be package imports. Specifically import paths that don't start with a path segment of/or.or..are considered to be package imports. The only two exceptions to this rule are subpath imports (which start with a#character) and TypeScript path remappings viapathsand/orbaseUrlintsconfig.json(which are applied first).Drop support for older platforms (#3802)
This release drops support for the following operating systems:
This is because the Go programming language dropped support for these operating system versions in Go 1.21, and this release updates esbuild from Go 1.20 to Go 1.22.
Note that this only affects the binary esbuild executables that are published to the
esbuildnpm package. It's still possible to compile esbuild's source code for these older operating systems. If you need to, you can compile esbuild for yourself using an older version of the Go compiler (before Go version 1.21). That might look something like this:In addition, this release increases the minimum required node version for esbuild's JavaScript API from node 12 to node 18. Node 18 is the oldest version of node that is still being supported (see node's release schedule for more information). This increase is because of an incompatibility between the JavaScript that the Go compiler generates for the
esbuild-wasmpackage and versions of node before node 17.4 (specifically thecrypto.getRandomValuesfunction).Update
await usingbehavior to match TypeScriptTypeScript 5.5 subtly changes the way
await usingbehaves. This release updates esbuild to match these changes in TypeScript. You can read more about these changes in microsoft/TypeScript#58624.Allow
es2024as a target environmentThe ECMAScript 2024 specification was just approved, so it has been added to esbuild as a possible compilation target. You can read more about the features that it adds here: https://2ality.com/2024/06/ecmascript-2024.html. The only addition that's relevant for esbuild is the regular expression
/vflag. With--target=es2024, regular expressions that use the/vflag will now be passed through untransformed instead of being transformed into a call tonew RegExp.Publish binaries for OpenBSD on 64-bit ARM (#3665, #3674)
With this release, you should now be able to install the
esbuildnpm package in OpenBSD on 64-bit ARM, such as on an Apple device with an M1 chip.This was contributed by @ikmckenz.
Publish binaries for WASI (WebAssembly System Interface) preview 1 (#3300, #3779)
The upcoming WASI (WebAssembly System Interface) standard is going to be a way to run WebAssembly outside of a JavaScript host environment. In this scenario you only need a
.wasmfile without any supporting JavaScript code. Instead of JavaScript providing the APIs for the host environment, the WASI standard specifies a "system interface" that WebAssembly code can access directly (e.g. for file system access).Development versions of the WASI specification are being released using preview numbers. The people behind WASI are currently working on preview 2 but the Go compiler has released support for preview 1, which from what I understand is now considered an unsupported legacy release. However, some people have requested that esbuild publish binary executables that support WASI preview 1 so they can experiment with them.
This release publishes esbuild precompiled for WASI preview 1 to the
@esbuild/wasi-preview1package on npm (specifically the file@esbuild/wasi-preview1/esbuild.wasm). This binary executable has not been tested and won't be officially supported, as it's for an old preview release of a specification that has since moved in another direction. If it works for you, great! If not, then you'll likely have to wait for the ecosystem to evolve before using esbuild with WASI. For example, it sounds like perhaps WASI preview 1 doesn't include support for opening network sockets so esbuild's local development server is unlikely to work with WASI preview 1.Warn about
onResolveplugins not setting a path (#3790)Plugins that return values from
onResolvewithout resolving the path (i.e. without setting eitherpathorexternal: true) will now cause a warning. This is because esbuild only uses return values fromonResolveif it successfully resolves the path, and it's not good for invalid input to be silently ignored.Add a new Go API for running the CLI with plugins (#3539)
With esbuild's Go API, you can now call
cli.RunWithPlugins(args, plugins)to pass an array of esbuild plugins to be used during the build process. This allows you to create a CLI that behaves similarly to esbuild's CLI but with additional Go plugins enabled.This was contributed by @edewit.
v0.21.5
Fix
Symbol.metadataon classes without a class decorator (#3781)This release fixes a bug with esbuild's support for the decorator metadata proposal. Previously esbuild only added the
Symbol.metadataproperty to decorated classes if there was a decorator on the class element itself. However, the proposal says that theSymbol.metadataproperty should be present on all classes that have any decorators at all, not just those with a decorator on the class element itself.Allow unknown import attributes to be used with the
copyloader (#3792)Import attributes (the
withkeyword onimportstatements) are allowed to alter how that path is loaded. For example, esbuild cannot assume that it knows how to load./bagel.jsas typebagel:Because of that, bundling this code with esbuild is an error unless the file
./bagel.jsis external to the bundle (such as with--bundle --external:./bagel.js).However, there is an additional case where it's ok for esbuild to allow this: if the file is loaded using the
copyloader. That's because thecopyloader behaves similarly to--externalin that the file is left external to the bundle. The difference is that thecopyloader copies the file into the output folder and rewrites the import path while--externaldoesn't. That means the following will now work with thecopyloader (such as with--bundle --loader:.bagel=copy):Support import attributes with glob-style imports (#3797)
This release adds support for import attributes (the
withoption) to glob-style imports (dynamic imports with certain string literal patterns as paths). These imports previously didn't support import attributes due to an oversight. So code like this will now work correctly:Previously this didn't work even though esbuild normally supports forcing the JSON loader using an import attribute. Attempting to do this used to result in the following error:
In addition, this change means plugins can now access the contents of
withfor glob-style imports.Support
${configDir}intsconfig.jsonfiles (#3782)This adds support for a new feature from the upcoming TypeScript 5.5 release. The character sequence
${configDir}is now respected at the start ofbaseUrlandpathsvalues, which are used by esbuild during bundling to correctly map import paths to file system paths. This feature lets basetsconfig.jsonfiles specified viaextendsrefer to the directory of the top-leveltsconfig.jsonfile. Here is an example:You can read more in TypeScript's blog post about their upcoming 5.5 release. Note that this feature does not make use of template literals (you need to use
"${configDir}/dist/js/*"not`${configDir}/dist/js/*`). The syntax fortsconfig.jsonis still just JSON with comments, and JSON syntax does not allow template literals. This feature only recognizes${configDir}in strings for certain path-like properties, and only at the beginning of the string.Fix internal error with
--supported:object-accessors=false(#3794)This release fixes a regression in 0.21.0 where some code that was added to esbuild's internal runtime library of helper functions for JavaScript decorators fails to parse when you configure esbuild with
--supported:object-accessors=false. The reason is that esbuild introduced code that does{ get [name]() {} }which uses both theobject-extensionsfeature for the[name]and theobject-accessorsfeature for theget, but esbuild was incorrectly only checking forobject-extensionsand not forobject-accessors. Additional tests have been added to avoid this type of issue in the future. A workaround for this issue in earlier releases is to also add--supported:object-extensions=false.v0.21.4
Update support for import assertions and import attributes in node (#3778)
Import assertions (the
assertkeyword) have been removed from node starting in v22.0.0. So esbuild will now strip them and generate a warning with--target=node22or above:Import attributes (the
withkeyword) have been backported to node 18 starting in v18.20.0. So esbuild will no longer strip them with--target=node18.NifNis 20 or greater.Fix
for awaittransform when a label is presentThis release fixes a bug where the
for awaittransform, which wraps the loop in atrystatement, previously failed to also move the loop's label into thetrystatement. This bug only affects code that uses both of these features in combination. Here's an example of some affected code:Do additional constant folding after cross-module enum inlining (#3416, #3425)
This release adds a few more cases where esbuild does constant folding after cross-module enum inlining.
Pass import attributes to on-resolve plugins (#3384, #3639, #3646)
With this release, on-resolve plugins will now have access to the import attributes on the import via the
withproperty of the arguments object. This mirrors thewithproperty of the arguments object that's already passed to on-load plugins. In addition, you can now passwithto theresolve()API call which will then forward that value on to all relevant plugins. Here's an example of a plugin that can now be written:Formatting support for the
@position-tryrule (#3773)Chrome shipped this new CSS at-rule in version 125 as part of the CSS anchor positioning API. With this release, esbuild now knows to expect a declaration list inside of the
@position-trybody block and will format it appropriately.Always allow internal string import and export aliases (#3343)
Import and export names can be string literals in ES2022+. Previously esbuild forbid any usage of these aliases when the target was below ES2022. Starting with this release, esbuild will only forbid such usage when the alias would otherwise end up in output as a string literal. String literal aliases that are only used internally in the bundle and are "compiled away" are no longer errors. This makes it possible to use string literal aliases with esbuild's
injectfeature even when the target is earlier than ES2022.v0.21.3
Implement the decorator metadata proposal (#3760)
This release implements the decorator metadata proposal, which is a sub-proposal of the decorators proposal. Microsoft shipped the decorators proposal in TypeScript 5.0 and the decorator metadata proposal in TypeScript 5.2, so it's important that esbuild also supports both of these features. Here's a quick example:
⚠️ WARNING ⚠️
This proposal has been marked as "stage 3" which means "recommended for implementation". However, it's still a work in progress and isn't a part of JavaScript yet, so keep in mind that any code that uses JavaScript decorator metadata may need to be updated as the feature continues to evolve. If/when that happens, I will update esbuild's implementation to match the specification. I will not be supporting old versions of the specification.
Fix bundled decorators in derived classes (#3768)
In certain cases, bundling code that uses decorators in a derived class with a class body that references its own class name could previously generate code that crashes at run-time due to an incorrect variable name. This problem has been fixed. Here is an example of code that was compiled incorrectly before this fix:
Fix
tsconfig.jsonfiles inside symlinked directories (#3767)This release fixes an issue with a scenario involving a
tsconfig.jsonfile thatextendsanother file from within a symlinked directory that uses thepathsfeature. In that case, the implicitbaseURLvalue should be based on the real path (i.e. after expanding all symbolic links) instead of the original path. This was already done for other files that esbuild resolves but was not yet done fortsconfig.jsonbecause it's special-cased (the regular path resolver can't be used because the information insidetsconfig.jsonis involved in path resolution). Note that this fix no longer applies if the--preserve-symlinkssetting is enabled.v0.21.2
Correct
thisin field and accessor decorators (#3761)This release changes the value of
thisin initializers for class field and accessor decorators from the module-levelthisvalue to the appropriatethisvalue for the decorated element (either the class or the instance). It was previously incorrect due to lack of test coverage. Here's an example of a decorator that doesn't work without this change:Allow
es2023as a target environment (#3762)TypeScript recently added
es2023as a compilation target, so esbuild now supports this too. There is no difference between a target ofes2022andes2023as far as esbuild is concerned since the 2023 edition of JavaScript doesn't introduce any new syntax features.v0.21.1
Fix a regression with
--keep-names(#3756)The previous release introduced a regression with the
--keep-namessetting and object literals withget/setaccessor methods, in which case the generated code contained syntax errors. This release fixes the regression:v0.21.0
This release doesn't contain any deliberately-breaking changes. However, it contains a very complex new feature and while all of esbuild's tests pass, I would not be surprised if an important edge case turns out to be broken. So I'm releasing this as a breaking change release to avoid causing any trouble. As usual, make sure to test your code when you upgrade.
Implement the JavaScript decorators proposal (#104)
With this release, esbuild now contains an implementation of the upcoming JavaScript decorators proposal. This is the same feature that shipped in TypeScript 5.0 and has been highly-requested on esbuild's issue tracker. You can read more about them in that blog post and in this other (now slightly outdated) extensive blog post here: https://2ality.com/2022/10/javascript-decorators.html. Here's a quick example:
Note that this feature is different than the existing "TypeScript experimental decorators" feature that esbuild already implements. It uses similar syntax but behaves very differently, and the two are not compatible (although it's sometimes possible to write decorators that work with both). TypeScript experimental decorators will still be supported by esbuild going forward as they have been around for a long time, are very widely used, and let you do certain things that are not possible with JavaScript decorators (such as decorating function parameters). By default esbuild will parse and transform JavaScript decorators, but you can tell esbuild to parse and transform TypeScript experimental decorators instead by setting
"experimentalDecorators": truein yourtsconfig.jsonfile.Probably at least half of the work for this feature went into creating a test suite that exercises many of the proposal's edge cases: https://github.com/evanw/decorator-tests. It has given me a reasonable level of confidence that esbuild's initial implementation is acceptable. However, I don't have access to a significant sample of real code that uses JavaScript decorators. If you're currently using JavaScript decorators in a real code base, please try out esbuild's implementation and let me know if anything seems off.
⚠️ WARNING ⚠️
This proposal has been in the works for a very long time (work began around 10 years ago in 2014) and it is finally getting close to becoming part of the JavaScript language. However, it's still a work in progress and isn't a part of JavaScript yet, so keep in mind that any code that uses JavaScript decorators may need to be updated as the feature continues to evolve. The decorators proposal is pretty close to its final form but it can and likely will undergo some small behavioral adjustments before it ends up becoming a part of the standard. If/when that happens, I will update esbuild's implementation to match the specification. I will not be supporting old versions of the specification.
Optimize the generated code for private methods
Previously when lowering private methods for old browsers, esbuild would generate one
WeakSetfor each private method. This mirrors similar logic for generating oneWeakSetfor each private field. Using a separateWeakMapfor private fields is necessary as their assignment can be observable:This prints
true falsebecause this partially-initialized instance has#xbut not#y. In other words, it's not true that all class instances will always have all of their private fields. However, the assignment of private methods to a class instance is not observable. In other words, it's true that all class instances will always have all of their private methods. This means esbuild can lower private methods into code where all methods share a singleWeakSet, which is smaller, faster, and uses less memory. Other JavaScript processing tools such as the TypeScript compiler already make this optimization. Here's what this change looks like:Fix an obscure bug with lowering class members with computed property keys
When class members that use newer syntax features are transformed for older target environments, they sometimes need to be relocated. However, care must be taken to not reorder any side effects caused by computed property keys. For example, the following code must evaluate
a()thenb()thenc():Previously esbuild did this by shifting the computed property key forward to the next spot in the evaluation order. Classes evaluate all computed keys first and then all static class elements, so if the last computed key needs to be shifted, esbuild previously inserted a static block at start of the class body, ensuring it came before all other static class elements:
However, this could cause esbuild to accidentally generate a syntax error if the computed property key contains code that isn't allowed in a static block, such as an
awaitexpression. With this release, esbuild fixes this problem by shifting the computed property key backward to the previous spot in the evaluation order instead, which may push it into theextendsclause or even before the class itself:Fix some
--keep-namesedge casesThe
NamedEvaluationsyntax-directed operation in the JavaScript specification gives certain anonymous expressions anameproperty depending on where they are in the syntax tree. For example, the following initializers convey anamevalue:When you enable esbuild's
--keep-namessetting, esbuild generates additional code to represent thisNamedEvaluationoperation so that the value of thenameproperty persists even when the identifiers are renamed (e.g. due to minification).However, I recently learned that esbuild's implementation of
NamedEvaluationis missing a few cases. Specifically esbuild was missing property definitions, class initializers, logical-assignment operators. These cases should now all be handled:v0.20.2
Support TypeScript experimental decorators on
abstractclass fields (#3684)With this release, you can now use TypeScript experimental decorators on
abstractclass fields. This was silently compiled incorrectly in esbuild 0.19.7 and below, and was an error from esbuild 0.19.8 to esbuild 0.20.1. Code such as the following should now work correctly:JSON loader now preserves
__proto__properties (#3700)Copying JSON source code into a JavaScript file will change its meaning if a JSON object contains the
__proto__key. A literal__proto__property in a JavaScript object literal sets the prototype of the object instead of adding a property named__proto__, while a literal__proto__property in a JSON object literal just adds a property named__proto__. With this release, esbuild will now work around this problem by converting JSON to JavaScript with a computed property key in this case:Improve dead code removal of
switchstatements (#3659)With this release, esbuild will now remove
switchstatements in branches when minifying if they are known to never be evaluated:Empty enums should behave like an object literal (#3657)
TypeScript allows you to create an empty enum and add properties to it at run time. While people usually use an empty object literal for this instead of a TypeScript enum, esbuild's enum transform didn't anticipate this use case and generated
undefinedinstead of{}for an empty enum. With this release, you can now use an empty enum to generate an empty object literal.Handle Yarn Plug'n'Play edge case with
tsconfig.json(#3698)Previously a
tsconfig.jsonfile thatextendsanother file in a package with anexportsmap failed to work when Yarn's Plug'n'Play resolution was active. This edge case should work now starting with this release.Work around issues with Deno 1.31+ (#3682)
Version 0.20.0 of esbuild changed how the esbuild child process is run in esbuild's API for Deno. Previously it used
Deno.runbut that API is being removed in favor ofDeno.Command. As part of this change, esbuild is now calling the newunreffunction on esbuild's long-lived child process, which is supposed to allow Deno to exit when your code has finished running even though the child process is still around (previously you had to explicitly call esbuild'sstop()function to terminate the child process for Deno to be able to exit).However, this introduced a problem for Deno's testing API which now fails some tests that use esbuild with
error: Promise resolution is still pending but the event loop has already resolved. It's unclear to me why this is happening. The call tounrefwas recommended by someone on the Deno core team, and calling Node's equivalentunrefAPI has been working fine for esbuild in Node for a long time. It could be that I'm using it incorrectly, or that there's some reference counting and/or garbage collection bug in Deno's internals, or that Deno'sunrefjust works differently than Node'sunref. In any case, it's not good for Deno tests that use esbuild to be failing.In this release, I am removing the call to
unrefto fix this issue. This means that you will now have to call esbuild'sstop()function to allow Deno to exit, just like you did before esbuild version 0.20.0 when this regression was introduced.Note: This regression wasn't caught earlier because Deno doesn't seem to fail tests that have outstanding
setTimeoutcalls, which esbuild's test harness was using to enforce a maximum test runtime. Adding asetTimeoutwas allowing esbuild's Deno tests to succeed. So this regression doesn't necessarily apply to all people using tests in Deno.✨ This PR was created by Minori, your friendly dependency updater! 🌸
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.