Skip to content

Releases: evanw/esbuild

v0.8.52

25 Feb 05:10
Compare
Choose a tag to compare
  • Fix a concurrent map write with the --inject: feature (#878)

    This release fixes an issue where esbuild could potentially crash sometimes with a concurrent map write when using injected files and entry points that were neither relative nor absolute paths. This was an edge case where esbuild's low-level file subsystem was being used without being behind a mutex lock. This regression was likely introduced in version 0.8.21. The cause of the crash has been fixed.

  • Provide kind to onResolve plugins (#879)

    Plugins that add onResolve callbacks now have access to the kind parameter which tells you what kind of import is being resolved. It will be one of the following values:

    • "entry-point" in JS (api.ResolveEntryPoint in Go)

      An entry point provided by the user

    • "import-statement" in JS (api.ResolveJSImportStatement in Go)

      A JavaScript import or export statement

    • "require-call" in JS (api.ResolveJSRequireCall in Go)

      A JavaScript call to require(...) with a string argument

    • "dynamic-import" in JS (api.ResolveJSDynamicImport in Go)

      A JavaScript import(...) expression with a string argument

    • "require-resolve" in JS (api.ResolveJSRequireResolve in Go)

      A JavaScript call to require.resolve(...) with a string argument

    • "import-rule" in JS (api.ResolveCSSImportRule in Go)

      A CSS @import rule

    • "url-token" in JS (api.ResolveCSSURLToken in Go)

      A CSS url(...) token

    These values are pretty much identical to the kind field in the JSON metadata file.

v0.8.51

23 Feb 10:18
Compare
Choose a tag to compare
  • The stderr log format now contains line numbers after file names (#865)

    Error messages in stderr now have a line and column number after the file name.

    Before:

     > src/structs/RTree.js: warning: Duplicate key "compareMinX" in object literal
        469 │     compareMinX: function (a, b)
            ╵     ~~~~~~~~~~~
       src/structs/RTree.js: note: The original "compareMinX" is here
        206 │     compareMinX: compareNodeMinX,
            ╵     ~~~~~~~~~~~
    

    After:

     > src/structs/RTree.js:469:4: warning: Duplicate key "compareMinX" in object literal
        469 │     compareMinX: function (a, b)
            ╵     ~~~~~~~~~~~
       src/structs/RTree.js:206:4: note: The original "compareMinX" is here
        206 │     compareMinX: compareNodeMinX,
            ╵     ~~~~~~~~~~~
    

    This should make log messages slightly easier to parse if you want to parse stderr instead of using esbuild's API. Previously you needed a multi-line regular expression to get the line number, but now that the line number is duplicated in two places you should only need a single-line regular expression.

    Note that this is still the hacky way to get error information and is potentially unstable, since it will break if the log format changes. Log messages are mainly intended for humans. The straightforward and stable way to do this is still to use esbuild's API, which returns log messages as an array of objects.

  • Allow --define with import.meta

    The --define feature lets you replace specific identifiers and member expression chains with compile-time constants. However, it previously didn't work with import.meta because this is a special case in the grammar. The import keyword is not actually an identifier expression. This distinction isn't helpful though, and it's not unreasonable to want to use the --define feature to replace import.meta properties too.

    With this release, it's now possible to use e.g. --define:import.meta.foo=123 to replace specific properties accessed off of the import.meta object as well as to use e.g. --define:import.meta={\"foo\":123} to substitute the entire import.meta expression with something else.

  • Fix a race condition with multiple injected files (#871)

    Using multiple injected files could cause a data race that trips Go's race detector. The data race has been fixed in this release. The fix was contributed by @Deleplace.

  • Change --serve behavior to serve on all interfaces (#866)

    The default address for the --serve flag has changed from 127.0.0.1 (serve on the loopback interface) to 0.0.0.0 (serve on all interfaces). You can still manually specify either one using --serve=127.0.0.1:8000 or --serve=0.0.0.0:8000. This just changes the default behavior that happens when you pass --serve with no host address (or when you just use the --servedir= flag without --serve=).

    In addition, you can now also specify an IPv6 address. Previously there was a parsing issue that prevented this. For example, you can pass --serve=[::1]:8000 to serve on the loopback interface and --serve=[::]:8000 to serve on all interfaces.

  • Change the import resolution rules of absolute paths (#862)

    Previously absolute paths were considered to be pre-resolved by the resolver (in contrast to relative and package paths, which need to be converted to an absolute path). This meant that absolute paths which did not actually exist caused a failure in the loader when it tried to load the path instead of in the resolver when it tried to resolve the path.

    With the previous change in version 0.8.47 to support removing URL query and/or hash parameters from the path, path resolution can now be run multiple times. If path resolution fails and the path contains a ? and/or #, path resolution is re-run with the URL query/hash parameters removed. It is problematic to consider absolute paths to be pre-resolved because it means that paths containing query/hash parameters make the loader try to load the wrong path, and do not run the resolver again with the parameter suffix removed.

    In this release, esbuild will now validate absolute paths in the resolver. So invalid paths will now fail in the resolver and retry without the parameter suffix instead of failing in the loader, which correctly handles a parameter suffix on absolute paths. In addition, this release now handles implicit file extensions on absolute paths. This makes esbuild a more accurate copy of node's module resolution algorithm, which does this as well.

  • Output files in metafile now have entryPoint (#711)

    There is now an optional entryPoint property on each output file in the JSON metadata file generated with the --metafile= flag. It is only present for output files that are the bundled results of entry point files, and contains the path name of the corresponding input entry point file. This property is not present on other kinds of output files (e.g. code splitting chunks). This feature was contributed by @remorses.

v0.8.50

21 Feb 10:42
Compare
Choose a tag to compare
  • Using direct eval now pulls in module and exports

    Use of direct eval forces the file to become a CommonJS module and disables dead code elimination in the entire file. The CommonJS closure is necessary to avoid name collisions with other modules, since eval means symbols in the file can no longer be renamed to avoid collisions.

    However, the CommonJS module and exports variables that are arguments to the closure previously weren't considered to be used in this scenario, meaning they may be omitted as dead code for size reasons. This could cause code inside eval to behave incorrectly. Now use of direct eval automatically counts as a use of both module and exports so these variables should now always be present in this case.

  • Always remove all "use asm" directives (#856)

    The asm.js subset of JavaScript has complicated validation rules that are triggered by this directive. The parser and code generator in esbuild was not designed with asm.js in mind and round-tripping asm.js code through esbuild will very likely cause it to no longer validate as asm.js. When this happens, V8 prints a warning and people don't like seeing the warning. The warning looks like this:

    (node:58335) V8: example.js:3 Invalid asm.js: Unexpected token
    (Use `node --trace-warnings ...` to show where the warning was created)
    

    I am deliberately not attempting to preserve the validity of asm.js code because it's a complicated legacy format and it's obsolete now that WebAssembly exists. By removing all "use asm" directives, the code will just become normal JavaScript and work fine without generating a warning.

  • Fix a variable hoisting edge case (#857)

    It is allowed to use a nested var hoisted declaration with the same name as a top-level function declaration. In that case the two symbols should merge and be treated as the same symbol:

    async function x() {}
    {
      var x;
    }

    The parser previously allowed this for regular functions but not for async or generator functions. Now with this release, this behavior is also allowed for these special kinds of functions too.

  • Remove empty CSS rules when minifying (#851)

    Empty rules with no content such as div {} are now removed when CSS is minified. This change was contributed by @susiwen8.

v0.8.49

19 Feb 08:36
Compare
Choose a tag to compare
  • Work around a problem with pnpm and NODE_PATH (#816)

    In version 0.8.43, esbuild added support for node's NODE_PATH environment variable which contains a list of global folders to use during path resolution. However, this causes a problem when esbuild is installed with pnpm, an alternative JavaScript package manager. Specifically pnpm adds a bogus path to NODE_PATH that doesn't exist but that has a file as a parent directory. Previously this caused esbuild to fail with the error not a directory. Now with this release, esbuild will ignore this bogus path instead of giving an error.

  • Add more names to the global no-side-effect list (#842)

    This release adds almost all known globals from the browser and node to the list of known globals. Membership in this list means accessing the global is assumed to have no side effects. That means tree shaking is allowed to remove unused references to these globals. For example, since HTMLElement is now in the known globals list, the following class will now be removed when unused:

    class MyElement extends HTMLElement {
    }

    In addition, membership in this list relaxes ordering constraints for the purposes of minification. It allows esbuild to reorder references to these globals past other expressions. For example, since console.log is now in the known globals list, the following simplification will now be performed during minification:

    // Original
    export default (a) => {
      if (a) console.log(b); else console.log(c)
    }
    
    // Minified (previous release)
    export default (a) => {
      a ? console.log(b) : console.log(c);
    };
    
    // Minified (this release)
    export default (a) => {
      console.log(a ? b : c);
    };

    This transformation is not generally safe because the console.log property access might evaluate code which could potentially change the value of a. This is only considered safe in this instance because console.log is now in the known globals list.

    Note that membership in this list does not say anything about whether the function has side effects when called. It only says that the identifier has no side effects when referenced. So console.log() is still considered to have side effects even though console.log is now considered to be free of side effects.

    The following globals are not on the list and are considered to have side effects:

    • scrollX
    • scrollY
    • innerWidth
    • innerHeight
    • pageXOffset
    • pageYOffset
    • localStorage
    • sessionStorage

    Accessing layout-related properties can trigger a layout and accessing storage-related properties can throw an exception if certain privacy settings are enabled. Both of these behaviors are considered side effects.

  • Fix a TypeScript parser regression (#846)

    Restrictions on array and object destructuring patterns in the previous release introduced a regression where arrays or objects in TypeScript code could fail to parse if they were wrapped in a double layer of parentheses. This was due to the speculative parsing of arrow function arguments. The regression has been fixed.

  • Add the Go-specific cli.ParseServeOptions() API (#834)

    This API is specifically for people trying to emulate esbuild's CLI in Go. It lets you share esbuild's logic of parsing the --serve= and --servedir= flags. Use it like this:

    serveOptions, args, err := cli.ParseServeOptions([]string{
      "--serve=8000",
    })
    buildOptions, err := cli.ParseBuildOptions(args)
    result := api.Serve(serveOptions, buildOptions)

v0.8.48

18 Feb 14:17
Compare
Choose a tag to compare
  • Fix some parsing edge cases (#835)

    This release fixes the following edge cases:

    • Code using in inside a template literal inside a for loop initializer such as for (let x = `${a in b ? '0' : '1'}`; false; ); is now allowed. Previously the in operator was incorrectly considered to be part of a for-in loop.

    • In TypeScript, it's not valid to have a newline in between the async and the < tokens inside the code async <T>() => {}. Previously this was incorrectly treated as an asynchronous arrow function expression.

    • Code of the form new async() must construct the function called async. Previously this was incorrectly treated as new (async())() instead due to the speculative parsing of asynchronous arrow functions.

    • Code of the form new async () => {} must not be allowed. Previously this was incorrectly allowed since the speculative parsing of asynchronous arrow functions did not check the precedence level.

    • It's not valid to start an initializer expression in a for-of loop with the token let such as for (let.foo of bar) {}. This is now forbidden. In addition, the code generator now respects this rule so for ((let.foo) of bar) {} is now printed as for ((let).foo of bar) {}.

    • Array and object binding patterns do not allow a comma after rest elements, so code such as [...a, b] = [c] is invalid. This case is correctly handled by esbuild. However, it's possible to have both an array or object binding pattern and an array or object literal on the left-hand side of a destructuring assignment such as [[...a, b].c] = [d]. In that case it should be allowed for a comma to come after the spread element in the array or object literal expression. Previously this was incorrectly treated as an error by esbuild.

    • It's technically allowed (although perhaps not ever actually useful) to call super() from within a default argument initializer like this:

      class Derived extends Base {
        constructor(arg = super()) {
        }
      }

      Previously esbuild did not permit this, which is incorrect. Doing this is now permitted.

    • It is an error to use arguments in a class field initializer such as class { x = arguments[0] }, but it is not an error to use arguments in a computed class property name such as class { [arguments[0]] = x } or inside TypeScript decorators such as class { @decorator(arguments[0]) x() {} }. Previously all of these cases were an error in esbuild, which is incorrect. Using arguments inside computed class property names and TypeScript decorators is now allowed.

    • It is not permitted to use a function declaration inside an if statement such as if (0) function f() {} in strict mode. Previously this was allowed, but this is now forbidden.

    • It is not permitted to re-declare a generator and/or asynchronous function declaration inside a block scope:

      // This is allowed
      function *a() {}
      function *a() {}
      
      // This is allowed
      function f() {
        function *b() {}
        function *b() {}
      }
      
      // This is not allowed
      {
        function *c() {}
        function *c() {}
      }

      The parser now enforces this rule.

    • Legacy octal escape sequences are octal escape sequences other than \0 with a single zero. These are forbidden in untagged template literals and in all strings in strict mode code. Previously esbuild didn't enforce this rule, but it is now enforced.

    • Technically the directive prologue is allowed to contain multiple directives, so strict mode should still be applied even if a "use strict"; directive is preceded by another directive. For example, "use \000"; "use strict"; should be a syntax error because strict mode is active. This technicality has now been implemented.

    • It is supposed to be a syntax error if a use strict directive is inside a function with a non-simple parameter list, such as (x = 1) => { 'use strict' }. Previously esbuild allowed this code, but now this code is a syntax error.

    • It is forbidden for a template literal tag to be an optional chain such as a?.b`c`. This rule is now enforced by esbuild, so code like this is now a syntax error. In addition, the code generator now avoids generating this syntax by wrapping any optional chain template literal tags in parentheses.

    • According to the standard, all code inside a class statement or expression should be in strict mode. Previously esbuild treated code inside a class as the same strict mode status as the surrounding code, but now code in a class is always interpreted as strict mode code.

    • Duplicate bindings in the same parameter list are not allowed if the parameter list isn't simple, such as in the code function f(a, [a]) {}, or if the parameter list belongs to an arrow function or a method. This rule is now enforced by esbuild's parser, so doing this is now a syntax error.

    • Array and object destructuring patterns are only valid if they are not surrounded by parentheses. Previously esbuild incorrectly allowed code such as ([]) = [] and ({}) = {}. This invalid code is now a syntax error.

    • It is now an error to use the shorthand property syntax ({yield}) inside a generator and ({await}) inside an asynchronous function. Previously those cases were incorrectly allowed.

    • A newline in between async and a method name is no longer allowed. Instead, this is a syntax error inside an object literal and a class field inside a class body.

  • Remove the local web server feature from the WebAssembly package (#836)

    This feature didn't work anyway (maybe sockets don't work with Go's WebAssembly target?) and including it added around 3mb of unnecessary extra code to the WebAssembly module file. Removing this brings the size of the WebAssembly module from around 11mb down to 8.3mb.

v0.8.47

18 Feb 02:04
Compare
Choose a tag to compare
  • Release native binaries for the Apple M1 chip (#550)

    Previously installing esbuild on a M1 actually installed the x86-64 version, which required the Rosetta 2 translator. This was because Go hadn't yet released support for the M1. Now that Go 1.16.0 has been released, esbuild can support the M1 natively. It's supported by esbuild starting with this release. There are reports of the native version being 1.4x faster than the translated version. This change was contributed by @rtsao.

  • Omit warning about require.someProperty when targeting CommonJS (#812)

    The require.cache property allows introspecting the state of the require cache, generally without affecting what is imported/bundled.

    Since esbuild's static analyzer only detects direct calls to require, it currently warns about uses of require in any situation other than a direct call since that means the value is "escaping" the analyzer. This is meant to detect and warn about indirect calls such as ['fs', 'path'].map(require).

    However, this warning is not relevant when accessing a property off of the require object such as require.cache because a property access does not result in capturing the value of require. Now a warning is no longer generated for require.someProperty when the output format is cjs. This allows for the use of features such as require.cache and require.extensions. This fix was contributed by @huonw.

  • Support ignored URL parameters at the end of import paths (#826)

    If path resolution fails, ebuild will now try again with the URL query and/or fragment removed. This helps handle ancient CSS code like this that contains hacks for Internet Explorer:

    @font-face {
      src:
        url("./themes/default/assets/fonts/icons.eot?#iefix") format('embedded-opentype'),
        url("./themes/default/assets/fonts/icons.woff2") format('woff2'),
        url("./themes/default/assets/fonts/icons.woff") format('woff'),
        url("./themes/default/assets/fonts/icons.ttf") format('truetype'),
        url("./themes/default/assets/fonts/icons.svg#icons") format('svg');
    }

    Previously path resolution would fail because these files do not end with the .eot?#iefix or .svg#icons extensions. Now path resolution should succeed. The URL query and fragment are not unconditionally stripped because there is apparently code in the wild that uses # as a directory name. So esbuild will still try to resolve the full import path first and only try to reinterpret the path as a URL if that fails.

  • Prevent paths starting with / from being used as relative paths on Windows (#822)

    On Windows, absolute paths start with a drive letter such as C:\... instead of with a slash like /.... This means that paths starting with a / can actually be used as relative paths. For example, this means an import of /subfolder/image.png will match the file at the path ./subfolder/image.png. This is problematic for Windows users because they may accidentally make use of these paths and then try to run their code on a non-Windows platform only for it to fail to build.

    Now paths starting with a / are always treated as an absolute path on all platforms. This means you can no longer import files at a relative path that starts with / on Windows. You should be using a ./ prefix instead.

  • Warn when importing a path with the wrong case

    Importing a path with the wrong case (e.g. File.js instead of file.js) will work on Windows and sometimes on macOS because they have case-insensitive file systems, but it will never work on Linux because it has a case-sensitive file system. To help you make your code more portable and to avoid cross-platform build failures, esbuild now issues a warning when you do this.

v0.8.46

14 Feb 02:53
Compare
Choose a tag to compare
  • Fix minification of .0 in CSS (#804)

    If you write .0 instead of 0 in CSS and enabled --minify, esbuild would previously minify this token incorrectly (the token was deleted). This bug has been fixed and esbuild should now minify this token to 0.

  • Support range requests in local HTTP server

    The local HTTP server built in to esbuild now supports range requests, which are necessary for video playback in Safari. This means you can now use <video> tags in your HTML pages with esbuild's local HTTP server.

v0.8.45

13 Feb 10:56
Compare
Choose a tag to compare
  • Add the --servedir= flag (#796)

    The --serve flag starts a local web server and serves the files that would normally be written to the output directory. So for example if you had an entry point called src/app.ts and an output directory of --outdir=www/js, using esbuild with --serve would expose the generated output file via http://localhost:8000/app.js (but not write anything to www/js). This can then be used in combination with your normal development server (running concurrently on another port) by adding <script src="http://localhost:8000/app.js"></script> in your HTML file. So esbuild with the --serve flag is meant to augment your normal development server, not replace it.

    This release introduces a new --servedir= flag which gives you the option of replacing your normal development server with esbuild. The directory you pass here will be "underlayed" below the output directory. Specifically when an incoming HTTP request comes in esbuild will first check if it matches one of the generated output files and if so, serve the output file directly from memory. Otherwise esbuild will fall back to serving content from the serve directory on the file system. In other words, server's URL structure behaves like a normal file server in a world where esbuild had written the generated output files to the file system (even though the output files actually only exist in memory).

    So for example if you had an entry point called src/app.ts and an output directory of --outdir=www/js, using esbuild with --servedir=www would expose the entire contents of the www directory via http://localhost:8000/ except for the http://localhost:8000/js/app.js URL which would contain the compiled contents of src/app.ts. This lets you have a www/index.html file containing just <script src="/js/app.js"></script> and use one web server instead of two.

    The benefit of doing things this way is that you can use the exact same HTML pages in development and production. In development you can run esbuild with --servedir= and esbuild will serve the generated output files directly. For production you can omit that flag and esbuild will write the generated files to the file system. In both cases you should be getting the exact same result in the browser with the exact same code in both development and production.

    This will of course not support all workflows, but that's intentional. This is designed to be a quality-of-life improvement for the simple case of building a small static website with some HTML, JavaScript, and CSS. More advanced setups may prefer to avoid the --servedir= feature and e.g. configure a NGINX reverse proxy to esbuild's local server to integrate esbuild into a larger existing development setup.

    One unintended consequence of this feature is that esbuild can now be used as a general local HTTP server via esbuild --servedir=.. Without any entry points, esbuild won't actually build anything and will just serve files like a normal web server. This isn't the intended use case but it could perhaps be a useful side effect of this feature.

  • Remove absolute paths for disabled packages from source maps (#786)

    This change is similar to the one from the previous release for disabled files, but it applies to package paths instead of relative paths. It's relevant when using packages that override dependencies with alternative packages using the browser field in their package.json file. Using relative paths instead of absolute paths fixes a determinism issue where build output was different on different systems. This fix was contributed by @eelco.

  • Handle absolute paths in tsconfig.json (#792)

    Some automatically-generated tsconfig.json paths can have absolute paths in them. This is allowed by the TypeScript compiler (specifically in the paths and extends fields). With this release, esbuild now supports absolute paths in paths and extends too.

  • Change the watch mode output format (#793)

    Previously esbuild would print a "..." animation to the console while watch mode was scanning for changes. The intent of this was to a) not take up too much space in the terminal and b) show that esbuild's watch mode isn't frozen. Since the release I have gotten feedback that this isn't desirable. People want more feedback about what's happening and want to be able to run regexes over the stderr stream instead of using esbuild's actual API.

    This release changes the output format for watch mode. Now esbuild will print [watch] build started when watch mode triggers a rebuild and [watch] build finished when the rebuild is complete. Any build errors will be printed in between those two log messages.

    Note that this means esbuild's watch mode output is now more verbose, especially when there are frequent file changes. If you want to hide these new messages you can use --log-level= with a level other than info.

v0.8.44

11 Feb 06:27
Compare
Choose a tag to compare
  • Create a logo for esbuild (#61)

    This release introduces a logo for esbuild:

         

    Inspirations for the logo include:

    • The fast-forward symbol because esbuild is extremely fast and because one of esbuild's goals is to accelerate the evolution of the whole web tooling ecosystem.

    • The right-shift symbol because esbuild's production optimizations make your code smaller and because esbuild itself contains many low-level optimizations for speed.

    Having a logo for esbuild should make it easier to include esbuild in lists of other tools since the other tools often all have logos.

  • Add support for node's --preserve-symlinks flag (#781)

    This release adds the --preserve-symlinks flag which behaves like the corresponding flag in node. Without the flag, esbuild and node will use the real path (after resolving symlinks) as the identity of a file. This means that a given file can only be instantiated once. With the flag, esbuild and node will use the original path (without resolving symlinks) as the identity of a file. This means that a given file can be instantiated multiple times, once for every symlink pointing to it. Each copy will have its own identity so the resulting bundle may contain duplicate files. This option is useful if your code relies on this flag in node (or the resolve.symlinks setting in Webpack).

  • Ignore a leading byte order mark (BOM) in CSS files (#776)

    Some text editors insert a U+FEFF code point at the start of text files. This is a zero-width non-breaking space character. Using one at the start of a file is a convention which is meant to indicate that the contents of the file are UTF-8 encoded. When this is done, the character is called a byte order mark.

    Unlike JavaScript, CSS does not treat U+FEFF as whitespace. It is treated as an identifier instead. This was causing esbuild to misinterpret files starting with a BOM as starting with an extra identifier, which could then cause the initial CSS rule in the file to be parsed incorrectly.

    Now esbuild will skip over a BOM if it's present before beginning to parse CSS. This should prevent issues when working with these files.

  • Add message notes to the API

    The internal logging system has the ability to attach additional notes to messages to provide more information. These show up as additional log messages in the terminal when using the command-line interface. Here is an example of a note:

     > src/structs/RTree.js: warning: Duplicate key "compareMinX" in object literal
        469 │     compareMinX: function (a, b)
            ╵     ~~~~~~~~~~~
       src/structs/RTree.js: note: The original "compareMinX" is here
        206 │     compareMinX: compareNodeMinX,
            ╵     ~~~~~~~~~~~
    

    With this release, notes are also supported in the JS and Go APIs. This means you can now generate your own notes using plugins as well as inspect the notes generated by esbuild.

  • Add origin information to errors from plugins (#780)

    Errors thrown during JavaScript plugin callback evaluation will now be annoated to show where that plugin callback was registered. That looks like this:

     > example-plugin.js: error: [example-plugin] foo.bar is not a function
        15 │         foo.bar();
           ╵             ^
        at ./example-plugin.js:15:13
        at ./node_modules/esbuild/lib/main.js:750:34
    
       example-plugin.js: note: This error came from the "onLoad" callback registered here
        13 │       build.onLoad({ filter: /.*/ }, args => {
           ╵             ~~~~~~
        at setup (./example-plugin.js:13:13)
        at handlePlugins (./node_modules/esbuild/lib/main.js:668:7)
    

    This should make it easier to debug crashes in plugin code.

  • Fix a regression with the synchronous JavaScript API (#784)

    In version 0.8.39, a change was made to avoid dangling esbuild processes when node exits abnormally. The change introduced a periodic ping between the child esbuild process and its host process. If the ping doesn't go through, the child process is able to detect that the host process is no longer there. Then it knows to exit since it's no longer being used.

    This caused a problem with the synchronous JavaScript API calls which run the esbuild child process in a single-response mode. The ping message was interpreted as a second response and tripped up the message protocol. Pings are only useful for the asynchronous API calls. Running the pings during synchronous API calls was unintentional. With this release pings are no longer run for synchronous API calls so this regression should be fixed.

  • Remove absolute paths for disabled files from source maps (#785)

    Files can be ignored (i.e. set to empty) using the browser field in package.json. Specifically, you can set the browser field to a map where the key is the module name and the value is false. This is a convention followed by several bundlers including esbuild.

    Previously ignoring a file caused that file's path to appear as an absolute path in any generated source map. This is problematic because it means different source maps will be generated on different systems, since the absolute path contains system-specific directory information. Now esbuild will treat these paths the same way it treats other paths and will put a relative path in the source map.

v0.8.43

08 Feb 09:22
Compare
Choose a tag to compare
  • Support the XDG_CACHE_HOME environment variable (#757)

    On Linux, the install script for esbuild currently caches downloaded binary executables in ~/.cache/esbuild/bin. This change means esbuild will now try installing to $XDG_CACHE_HOME/esbuild/bin instead of the XDG_CACHE_HOME environment variable exists. This allows you to customize the cache directory on Linux. The specification that defines XDG_CACHE_HOME is here.

  • Further improve constant folding of branches (#765)

    At a high level, this release adds the following substitutions to improve constant folding and dead code elimination:

    • if (anything && falsyWithSideEffects)if (anything, falsyWithSideEffects)
    • if (anything || truthyWithSideEffects)if (anything, truthyWithSideEffects)
    • if (anything && truthyNoSideEffects)if (anything)
    • if (anything || falsyNoSideEffects)if (anything)
    • if (anything, truthyOrFalsy)anything; if (truthyOrFalsy)

    And also these substitutions for unused expressions:

    • primitive == primitiveprimitive, primitive
    • typeof identifier → (remove entirely)

    The actual substitutions are more complex since they are more comprehensive but they essentially result in this high-level behavior. Note that these substitutions are only done when minification is enabled.

  • Fix an edge case with CSS variable syntax (#760)

    CSS variables are whitespace-sensitive even though other CSS syntax is mostly not whitespace sensitive. It is apparently common for this to cause problems with CSS tooling that pretty-prints and minifies CSS, including esbuild before this release. Some examples of issues with other tools include postcss/postcss#1404 and tailwindlabs/tailwindcss#2889. The issue affects code like this:

    div {
      --some-var: ;
      some-decl: var(--some-var, );
    }

    It would be a change in semantics to minify this code to either --some-var:; or var(--some-var,) due to the whitespace significance of CSS variables, so such transformations are invalid. With this release, esbuild should now preserve whitespace in these two situations (CSS variable declarations and CSS variable references).

  • Add support for recursive symlinks during path resolution (#766)

    Previously recursive symlinks (a symlink that points to another symlink) were an unhandled case in the path resolution algorithm. Now these cases should be supported up to a depth of 256 symlinks. This means esbuild's path resolution should now work with multi-level yarn link scenarios.

  • Fix subtle circular dependency issue (#758)

    If esbuild is used to transform TypeScript to JavaScript without bundling (i.e. each file is transformed individually), the output format is CommonJS, and the original TypeScript code contains an import cycle where at least one of the links in the cycle is an export * as re-export statement, there could be certain situations where evaluating the transformed code results in an import being undefined. This is caused by the __esModule marker being added after the call to require() for the first transformed re-export statement. The fix was to move the marker to before the first call to require(). The __esModule marker is a convention from Babel that esbuild reuses which marks a module as being originally in the ECMAScript module format instead of the CommonJS module format.

  • Add support for the NODE_PATH environment variable

    This is a rarely-used feature of Node's module resolution algorithm. From the documentation:

    If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere.

    On Windows, NODE_PATH is delimited by semicolons (;) instead of colons.

    The CLI takes the list of node paths from the value of the NODE_PATH environment variable, but the JS and Go APIs take the list as an array of strings instead (called nodePaths in JS and NodePaths in Go).