@netlify/esbuild-linux-arm64
Advanced tools
Changelog
0.14.39
Fix code generation for export default
and /* @__PURE__ */
call (#2203)
The /* @__PURE__ */
comment annotation can be added to function calls to indicate that they are side-effect free. These annotations are passed through into the output by esbuild since many JavaScript tools understand them. However, there was an edge case where printing this comment before a function call caused esbuild to fail to parenthesize a function literal because it thought it was no longer at the start of the expression. This problem has been fixed:
// Original code
export default /* @__PURE__ */ (function() {
})()
// Old output
export default /* @__PURE__ */ function() {
}();
// New output
export default /* @__PURE__ */ (function() {
})();
Preserve ...
before JSX child expressions (#2245)
TypeScript 4.5 changed how JSX child expressions that start with ...
are emitted. Previously the ...
was omitted but starting with TypeScript 4.5, the ...
is now preserved instead. This release updates esbuild to match TypeScript's new output in this case:
// Original code
console.log(<a>{...b}</a>)
// Old output
console.log(/* @__PURE__ */ React.createElement("a", null, b));
// New output
console.log(/* @__PURE__ */ React.createElement("a", null, ...b));
Note that this behavior is TypeScript-specific. Babel doesn't support the ...
token at all (it gives the error "Spread children are not supported in React").
Slightly adjust esbuild's handling of the browser
field in package.json
(#2239)
This release changes esbuild's interpretation of browser
path remapping to fix a regression that was introduced in esbuild version 0.14.21. Browserify has a bug where it incorrectly matches package paths to relative paths in the browser
field, and esbuild replicates this bug for compatibility with Browserify. I have a set of tests that I use to verify that esbuild's replication of this Browserify is accurate here: https://github.com/evanw/package-json-browser-tests. However, I was missing a test case and esbuild's behavior diverges from Browserify in this case. This release now handles this edge case as well:
entry.js
:
require('pkg/sub')
node_modules/pkg/package.json
:
{
"browser": {
"./sub": "./sub/foo.js",
"./sub/sub.js": "./sub/foo.js"
}
}
node_modules/pkg/sub/foo.js
:
require('sub')
node_modules/sub/index.js
:
console.log('works')
The import path sub
in require('sub')
was previously matching the remapping "./sub/sub.js": "./sub/foo.js"
but with this release it should now no longer match that remapping. Now require('sub')
will only match the remapping "./sub/sub": "./sub/foo.js"
(without the trailing .js
). Browserify apparently only matches without the .js
suffix here.
Changelog
0.14.25
Reduce minification of CSS transforms to avoid Safari bugs (#2057)
In Safari, applying a 3D CSS transform to an element can cause it to render in a different order than applying a 2D CSS transform even if the transformation matrix is identical. I believe this is a bug in Safari because the CSS transform
specification doesn't seem to distinguish between 2D and 3D transforms as far as rendering order:
For elements whose layout is governed by the CSS box model, any value other than
none
for thetransform
property results in the creation of a stacking context.
This bug means that minifying a 3D transform into a 2D transform must be avoided even though it's a valid transformation because it can cause rendering differences in Safari. Previously esbuild sometimes minified 3D CSS transforms into 2D CSS transforms but with this release, esbuild will no longer do that:
/* Original code */
div { transform: matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) }
/* Old output (with --minify) */
div{transform:scale(2)}
/* New output (with --minify) */
div{transform:scale3d(2,2,1)}
Minification now takes advantage of the ?.
operator
This adds new code minification rules that shorten code with the ?.
optional chaining operator when the result is equivalent:
// Original code
let foo = (x) => {
if (x !== null && x !== undefined) x.y()
return x === null || x === undefined ? undefined : x.z
}
// Old output (with --minify)
let foo=n=>(n!=null&&n.y(),n==null?void 0:n.z);
// New output (with --minify)
let foo=n=>(n?.y(),n?.z);
This only takes effect when minification is enabled and when the configured target environment is known to support the optional chaining operator. As always, make sure to set --target=
to the appropriate language target if you are running the minified code in an environment that doesn't support the latest JavaScript features.
Add source mapping information for some non-executable tokens (#1448)
Code coverage tools can generate reports that tell you if any code exists that has not been run (or "covered") during your tests. You can use this information to add additional tests for code that isn't currently covered.
Some popular JavaScript code coverage tools have bugs where they incorrectly consider lines without any executable code as uncovered, even though there's no test you could possibly write that would cause those lines to be executed. For example, they apparently complain about the lines that only contain the trailing }
token of an object literal.
With this release, esbuild now generates source mappings for some of these trailing non-executable tokens. This may not successfully work around bugs in code coverage tools because there are many non-executable tokens in JavaScript and esbuild doesn't map them all (the drawback of mapping these extra tokens is that esbuild will use more memory, build more slowly, and output a bigger source map). The true solution is to fix the bugs in the code coverage tools in the first place.
Fall back to WebAssembly on Android x64 (#2068)
Go's compiler supports trivial cross-compiling to almost all platforms without installing any additional software other than the Go compiler itself. This has made it very easy for esbuild to publish native binary executables for many platforms. However, it strangely doesn't support cross-compiling to Android x64 without installing the Android build tools. So instead of publishing a native esbuild binary executable to npm, this release publishes a WebAssembly fallback build. This is essentially the same as the esbuild-wasm
package but it's installed automatically when you install the esbuild
package on Android x64. So packages that depend on the esbuild
package should now work on Android x64. If you want to use a native binary executable of esbuild on Android x64, you may be able to build it yourself from source after installing the Android build tools.
Update to Go 1.17.8
The version of the Go compiler used to compile esbuild has been upgraded from Go 1.17.7 to Go 1.17.8, which fixes the RISC-V 64-bit build. Compiler optimizations for the RISC-V 64-bit build have now been re-enabled.
Changelog
0.14.23
Update feature database to indicate that node 16.14+ supports import assertions (#2030)
Node versions 16.14 and above now support import assertions according to these release notes. This release updates esbuild's internal feature compatibility database with this information, so esbuild no longer strips import assertions with --target=node16.14
:
// Original code
import data from './package.json' assert { type: 'json' }
console.log(data)
// Old output (with --target=node16.14)
import data from "./package.json";
console.log(data);
// New output (with --target=node16.14)
import data from "./package.json" assert { type: "json" };
console.log(data);
Basic support for CSS @layer
rules (#2027)
This adds basic parsing support for a new CSS feature called @layer
that changes how the CSS cascade works. Adding parsing support for this rule to esbuild means esbuild can now minify the contents of @layer
rules:
/* Original code */
@layer a {
@layer b {
div {
color: yellow;
margin: 0.0px;
}
}
}
/* Old output (with --minify) */
@layer a{@layer b {div {color: yellow; margin: 0px;}}}
/* New output (with --minify) */
@layer a.b{div{color:#ff0;margin:0}}
You can read more about @layer
here:
Note that the support added in this release is only for parsing and printing @layer
rules. The bundler does not yet know about these rules and bundling with @layer
may result in behavior changes since these new rules have unusual ordering constraints that behave differently than all other CSS rules. Specifically the order is derived from the first instance while with every other CSS rule, the order is derived from the last instance.
Changelog
0.13.13
Add more information about skipping "main"
in package.json
(#1754)
Configuring mainFields: []
breaks most npm packages since it tells esbuild to ignore the "main"
field in package.json
, which most npm packages use to specify their entry point. This is not a bug with esbuild because esbuild is just doing what it was told to do. However, people may do this without understanding how npm packages work, and then be confused about why it doesn't work. This release now includes additional information in the error message:
> foo.js:1:27: error: Could not resolve "events" (use "--platform=node" when building for node)
1 │ var EventEmitter = require('events')
╵ ~~~~~~~~
node_modules/events/package.json:20:2: note: The "main" field was ignored because the list of main fields to use is currently set to []
20 │ "main": "./events.js",
╵ ~~~~~~
Fix a tree-shaking bug with var exports
(#1739)
This release fixes a bug where a variable named var exports = {}
was incorrectly removed by tree-shaking (i.e. dead code elimination). The exports
variable is a special variable in CommonJS modules that is automatically provided by the CommonJS runtime. CommonJS modules are transformed into something like this before being run:
function(exports, module, require) {
var exports = {}
}
So using var exports = {}
should have the same effect as exports = {}
because the variable exports
should already be defined. However, esbuild was incorrectly overwriting the definition of the exports
variable with the one provided by CommonJS. This release merges the definitions together so both are included, which fixes the bug.
Merge adjacent CSS selector rules with duplicate content (#1755)
With this release, esbuild will now merge adjacent selectors when minifying if they have the same content:
/* Original code */
a { color: red }
b { color: red }
/* Old output (with --minify) */
a{color:red}b{color:red}
/* New output (with --minify) */
a,b{color:red}
Shorten top
, right
, bottom
, left
CSS property into inset
when it is supported (#1758)
This release enables collapsing of inset
related properties:
/* Original code */
div {
top: 0;
right: 0;
bottom: 0;
left: 0;
}
/* Output with "--minify-syntax" */
div {
inset: 0;
}
This minification rule is only enabled when inset
property is supported by the target environment. Make sure to set esbuild's target
setting correctly when minifying if the code will be running in an older environment (e.g. earlier than Chrome 87).
This feature was contributed by @sapphi-red.
Changelog
0.13.6
Emit decorators for declare
class fields (#1675)
In version 3.7, TypeScript introduced the declare
keyword for class fields that avoids generating any code for that field:
// TypeScript input
class Foo {
a: number
declare b: number
}
// JavaScript output
class Foo {
a;
}
However, it turns out that TypeScript still emits decorators for these omitted fields. With this release, esbuild will now do this too:
// TypeScript input
class Foo {
@decorator a: number;
@decorator declare b: number;
}
// Old JavaScript output
class Foo {
a;
}
__decorateClass([
decorator
], Foo.prototype, "a", 2);
// New JavaScript output
class Foo {
a;
}
__decorateClass([
decorator
], Foo.prototype, "a", 2);
__decorateClass([
decorator
], Foo.prototype, "b", 2);
Experimental support for esbuild on NetBSD (#1624)
With this release, esbuild now has a published binary executable for NetBSD in the esbuild-netbsd-64
npm 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 @gdt.
⚠️ 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. ⚠️
Disable the "esbuild was bundled" warning if ESBUILD_BINARY_PATH
is provided (#1678)
The ESBUILD_BINARY_PATH
environment variable allows you to substitute an alternate binary executable for esbuild's JavaScript API. This is useful in certain cases such as when debugging esbuild. The JavaScript API has some code that throws an error if it detects that it was bundled before being run, since bundling prevents esbuild from being able to find the path to its binary executable. However, that error is unnecessary if ESBUILD_BINARY_PATH
is present because an alternate path has been provided. This release disables the warning when ESBUILD_BINARY_PATH
is present so that esbuild can be used when bundled as long as you also manually specify ESBUILD_BINARY_PATH
.
This change was contributed by @heypiotr.
Remove unused catch
bindings when minifying (#1660)
With this release, esbuild will now remove unused catch
bindings when minifying:
// Original code
try {
throw 0;
} catch (e) {
}
// Old output (with --minify)
try{throw 0}catch(t){}
// New output (with --minify)
try{throw 0}catch{}
This takes advantage of the new optional catch binding syntax feature that was introduced in ES2019. This minification rule is only enabled when optional catch bindings are supported by the target environment. Specifically, it's not enabled when using --target=es2018
or older. Make sure to set esbuild's target
setting correctly when minifying if the code will be running in an older JavaScript environment.
This change was contributed by @sapphi-red.
Changelog
0.13.5
Improve watch mode accuracy (#1113)
Watch mode is enabled by --watch
and causes esbuild to become a long-running process that automatically rebuilds output files when input files are changed. It's implemented by recording all calls to esbuild's internal file system interface and then invalidating the build whenever these calls would return different values. For example, a call to esbuild's internal ReadFile()
function is considered to be different if either the presence of the file has changed (e.g. the file didn't exist before but now exists) or the presence of the file stayed the same but the content of the file has changed.
Previously esbuild's watch mode operated at the ReadFile()
and ReadDirectory()
level. When esbuild checked whether a directory entry existed or not (e.g. whether a directory contains a node_modules
subdirectory or a package.json
file), it called ReadDirectory()
which then caused the build to depend on that directory's set of entries. This meant the build would be invalidated even if a new unrelated entry was added or removed, since that still changes the set of entries. This is problematic when using esbuild in environments that constantly create and destroy temporary directory entries in your project directory. In that case, esbuild's watch mode would constantly rebuild as the directory was constantly considered to be dirty.
With this release, watch mode now operates at the ReadFile()
and ReadDirectory().Get()
level. So when esbuild checks whether a directory entry exists or not, the build should now only depend on the presence status for that one directory entry. This should avoid unnecessary rebuilds due to unrelated directory entries being added or removed. The log messages generated using --watch
will now also mention the specific directory entry whose presence status was changed if a build is invalidated for this reason.
Note that this optimization does not apply to plugins using the watchDirs
return value because those paths are only specified at the directory level and do not describe individual directory entries. You can use watchFiles
or watchDirs
on the individual entries inside the directory to get a similar effect instead.
Disallow certain uses of <
in .mts
and .cts
files
The upcoming version 4.5 of TypeScript is introducing the .mts
and .cts
extensions that turn into the .mjs
and .cjs
extensions when compiled. However, unlike the existing .ts
and .tsx
extensions, expressions that start with <
are disallowed when they would be ambiguous depending on whether they are parsed in .ts
or .tsx
mode. The ambiguity is caused by the overlap between the syntax for JSX elements and the old deprecated syntax for type casts:
| Syntax | .ts
| .tsx
| .mts
/.cts
|
|-------------------------------|----------------------|------------------|----------------------|
| <x>y
| ✅ Type cast | 🚫 Syntax error | 🚫 Syntax error |
| <T>() => {}
| ✅ Arrow function | 🚫 Syntax error | 🚫 Syntax error |
| <x>y</x>
| 🚫 Syntax error | ✅ JSX element | 🚫 Syntax error |
| <T>() => {}</T>
| 🚫 Syntax error | ✅ JSX element | 🚫 Syntax error |
| <T extends>() => {}</T>
| 🚫 Syntax error | ✅ JSX element | 🚫 Syntax error |
| <T extends={0}>() => {}</T>
| 🚫 Syntax error | ✅ JSX element | 🚫 Syntax error |
| <T,>() => {}
| ✅ Arrow function | ✅ Arrow function | ✅ Arrow function |
| <T extends X>() => {}
| ✅ Arrow function | ✅ Arrow function | ✅ Arrow function |
This release of esbuild introduces a syntax error for these ambiguous syntax constructs in .mts
and .cts
files to match the new behavior of the TypeScript compiler.
Do not remove empty @keyframes
rules (#1665)
CSS minification in esbuild automatically removes empty CSS rules, since they have no effect. However, empty @keyframes
rules still trigger JavaScript animation events so it's incorrect to remove them. To demonstrate that empty @keyframes
rules still have an effect, here is a bug report for Firefox where it was incorrectly not triggering JavaScript animation events for empty @keyframes
rules: https://bugzilla.mozilla.org/show_bug.cgi?id=1004377.
With this release, empty @keyframes
rules are now preserved during minification:
/* Original CSS */
@keyframes foo {
from {}
to {}
}
/* Old output (with --minify) */
/* New output (with --minify) */
@keyframes foo{}
This fix was contributed by @eelco.
Fix an incorrect duplicate label error (#1671)
When labeling a statement in JavaScript, the label must be unique within the enclosing statements since the label determines the jump target of any labeled break
or continue
statement:
// This code is valid
x: y: z: break x;
// This code is invalid
x: y: x: break x;
However, an enclosing label with the same name is allowed as long as it's located in a different function body. Since break
and continue
statements can't jump across function boundaries, the label is not ambiguous. This release fixes a bug where esbuild incorrectly treated this valid code as a syntax error:
// This code is valid, but was incorrectly considered a syntax error
x: (() => {
x: break x;
})();
This fix was contributed by @nevkontakte.
Changelog
0.13.4
Fix permission issues with the install script (#1642)
The esbuild
package contains a small JavaScript stub file that implements the CLI (command-line interface). Its only purpose is to spawn the binary esbuild executable as a child process and forward the command-line arguments to it.
The install script contains an optimization that replaces this small JavaScript stub with the actual binary executable at install time to avoid the overhead of unnecessarily creating a new node
process. This optimization can't be done at package publish time because there is only one esbuild
package but there are many supported platforms, so the binary executable for the current platform must live outside of the esbuild
package.
However, the optimization was implemented with an unlink operation followed by a link operation. This means that if the first step fails, the package is left in a broken state since the JavaScript stub file is deleted but not yet replaced.
With this release, the optimization is now implemented with a link operation followed by a rename operation. This should always leave the package in a working state even if either step fails.
Add a fallback for npm install esbuild --no-optional
(#1647)
The installation method for esbuild's platform-specific binary executable was recently changed in version 0.13.0. Before that version esbuild downloaded it in an install script, and after that version esbuild lets the package manager download it using the optionalDependencies
feature in package.json
. This change was made because downloading the binary executable in an install script never really fully worked. The reasons are complex but basically there are a variety of edge cases where people people want to install esbuild in environments that they have customized such that downloading esbuild isn't possible. Using optionalDependencies
instead lets the package manager deal with it instead, which should work fine in all cases (either that or your package manager has a bug, but that's not esbuild's problem).
There is one case where this new installation method doesn't work: if you pass the --no-optional
flag to npm to disable the optionalDependencies
feature. If you do this, you prevent esbuild from being installed. This is not a problem with esbuild because you are manually enabling a flag to change npm's behavior such that esbuild doesn't install correctly. However, people still want to do this.
With this release, esbuild will now fall back to the old installation method if the new installation method fails. THIS MAY NOT WORK. The new optionalDependencies
installation method is the only supported way to install esbuild with npm. The old downloading installation method was removed because it doesn't always work. The downloading method is only being provided to try to be helpful but it's not the supported installation method. If you pass --no-optional
and the download fails due to some environment customization you did, the recommended fix is to just remove the --no-optional
flag.
Support the new .mts
and .cts
TypeScript file extensions
The upcoming version 4.5 of TypeScript has two new file extensions: .mts
and .cts
. Files with these extensions can be imported using the .mjs
and .cjs
, respectively. So the statement import "./foo.mjs"
in TypeScript can actually succeed even if the file ./foo.mjs
doesn't exist on the file system as long as the file ./foo.mts
does exist. The import path with the .mjs
extension is automatically re-routed to the corresponding file with the .mts
extension at type-checking time by the TypeScript compiler. See the TypeScript 4.5 beta announcement for details.
With this release, esbuild will also automatically rewrite .mjs
to .mts
and .cjs
to .cts
when resolving import paths to files on the file system. This should make it possible to bundle code written in this new style. In addition, the extensions .mts
and .cts
are now also considered valid TypeScript file extensions by default along with the .ts
extension.
Fix invalid CSS minification of margin
and padding
(#1657)
CSS minification does collapsing of margin
and padding
related properties. For example:
/* Original CSS */
div {
margin: auto;
margin-top: 5px;
margin-left: 5px;
}
/* Minified CSS */
div{margin:5px auto auto 5px}
However, while this works for the auto
keyword, it doesn't work for other keywords. For example:
/* Original CSS */
div {
margin: inherit;
margin-top: 5px;
margin-left: 5px;
}
/* Minified CSS */
div{margin:inherit;margin-top:5px;margin-left:5px}
Transforming this to div{margin:5px inherit inherit 5px}
, as was done in previous releases of esbuild, is an invalid transformation and results in incorrect CSS. This release of esbuild fixes this CSS transformation bug.
Changelog
0.13.3
Support TypeScript type-only import/export specifiers (#1637)
This release adds support for a new TypeScript syntax feature in the upcoming version 4.5 of TypeScript. This feature lets you prefix individual imports and exports with the type
keyword to indicate that they are types instead of values. This helps tools such as esbuild omit them from your source code, and is necessary because esbuild compiles files one-at-a-time and doesn't know at parse time which imports/exports are types and which are values. The new syntax looks like this:
// Input TypeScript code
import { type Foo } from 'foo'
export { type Bar }
// Output JavaScript code (requires "importsNotUsedAsValues": "preserve" in "tsconfig.json")
import {} from "foo";
export {};
See microsoft/TypeScript#45998 for full details. From what I understand this is a purely ergonomic improvement since this was already previously possible using a type-only import/export statements like this:
// Input TypeScript code
import type { Foo } from 'foo'
export type { Bar }
import 'foo'
export {}
// Output JavaScript code (requires "importsNotUsedAsValues": "preserve" in "tsconfig.json")
import "foo";
export {};
This feature was contributed by @g-plane.
Changelog
0.13.2
Fix export {}
statements with --tree-shaking=true
(#1628)
The new --tree-shaking=true
option allows you to force-enable tree shaking in cases where it wasn't previously possible. One such case is when bundling is disabled and there is no output format configured, in which case esbuild just preserves the format of whatever format the input code is in. Enabling tree shaking in this context caused a bug where export {}
statements were stripped. This release fixes the bug so export {}
statements should now be preserved when you pass --tree-shaking=true
. This bug only affected this new functionality and didn't affect existing scenarios.