Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependency esbuild to ^0.17.0 #9

Merged
merged 2 commits into from
Jan 16, 2023
Merged

Update dependency esbuild to ^0.17.0 #9

merged 2 commits into from
Jan 16, 2023

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Jan 14, 2023

Mend Renovate

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
esbuild ^0.16.0 -> ^0.17.0 age adoption passing confidence

Release Notes

evanw/esbuild

v0.17.0

Compare Source

This release deliberately contains backwards-incompatible changes. To avoid automatically picking up releases like this, you should either be pinning the exact version of esbuild in your package.json file (recommended) or be using a version range syntax that only accepts patch upgrades such as ^0.16.0 or ~0.16.0. See npm's documentation about semver for more information.

At a high level, the breaking changes in this release fix some long-standing issues with the design of esbuild's incremental, watch, and serve APIs. This release also introduces some exciting new features such as live reloading. In detail:

  • Move everything related to incremental builds to a new context API (#​1037, #​1606, #​2280, #​2418)

    This change removes the incremental and watch options as well as the serve() method, and introduces a new context() method. The context method takes the same arguments as the build() method but only validates its arguments and does not do an initial build. Instead, builds can be triggered using the rebuild(), watch(), and serve() methods on the returned context object. The new context API looks like this:

    // Create a context for incremental builds
    const context = await esbuild.context({
      entryPoints: ['app.ts'],
      bundle: true,
    })
    
    // Manually do an incremental build
    const result = await context.rebuild()
    
    // Enable watch mode
    await context.watch()
    
    // Enable serve mode
    await context.serve()
    
    // Dispose of the context
    context.dispose()

    The switch to the context API solves a major issue with the previous API which is that if the initial build fails, a promise is thrown in JavaScript which prevents you from accessing the returned result object. That prevented you from setting up long-running operations such as watch mode when the initial build contained errors. It also makes tearing down incremental builds simpler as there is now a single way to do it instead of three separate ways.

    In addition, this release also makes some subtle changes to how incremental builds work. Previously every call to rebuild() started a new build. If you weren't careful, then builds could actually overlap. This doesn't cause any problems with esbuild itself, but could potentially cause problems with plugins (esbuild doesn't even give you a way to identify which overlapping build a given plugin callback is running on). Overlapping builds also arguably aren't useful, or at least aren't useful enough to justify the confusion and complexity that they bring. With this release, there is now only ever a single active build per context. Calling rebuild() before the previous rebuild has finished now "merges" with the existing rebuild instead of starting a new build.

  • Allow using watch and serve together (#​805, #​1650, #​2576)

    Previously it was not possible to use watch mode and serve mode together. The rationale was that watch mode is one way of automatically rebuilding your project and serve mode is another (since serve mode automatically rebuilds on every request). However, people want to combine these two features to make "live reloading" where the browser automatically reloads the page when files are changed on the file system.

    This release now allows you to use these two features together. You can only call the watch() and serve() APIs once each per context, but if you call them together on the same context then esbuild will automatically rebuild both when files on the file system are changed and when the server serves a request.

  • Support "live reloading" through server-sent events (#​802)

    Server-sent events are a simple way to pass one-directional messages asynchronously from the server to the client. Serve mode now provides a /esbuild endpoint with an change event that triggers every time esbuild's output changes. So you can now implement simple "live reloading" (i.e. reloading the page when a file is edited and saved) like this:

    new EventSource('/esbuild').addEventListener('change', () => location.reload())

    The event payload is a JSON object with the following shape:

    interface ChangeEvent {
      added: string[]
      removed: string[]
      updated: string[]
    }

    This JSON should also enable more complex live reloading scenarios. For example, the following code hot-swaps changed CSS <link> tags in place without reloading the page (but still reloads when there are other types of changes):

    new EventSource('/esbuild').addEventListener('change', e => {
      const { added, removed, updated } = JSON.parse(e.data)
      if (!added.length && !removed.length && updated.length === 1) {
        for (const link of document.getElementsByTagName("link")) {
          const url = new URL(link.href)
          if (url.host === location.host && url.pathname === updated[0]) {
            const next = link.cloneNode()
            next.href = updated[0] + '?' + Math.random().toString(36).slice(2)
            next.onload = () => link.remove()
            link.parentNode.insertBefore(next, link.nextSibling)
            return
          }
        }
      }
      location.reload()
    })

    Implementing live reloading like this has a few known caveats:

    • These events only trigger when esbuild's output changes. They do not trigger when files unrelated to the build being watched are changed. If your HTML file references other files that esbuild doesn't know about and those files are changed, you can either manually reload the page or you can implement your own live reloading infrastructure instead of using esbuild's built-in behavior.

    • The EventSource API is supposed to automatically reconnect for you. However, there's a bug in Firefox that breaks this if the server is ever temporarily unreachable: https://bugzilla.mozilla.org/show_bug.cgi?id=1809332. Workarounds are to use any other browser, to manually reload the page if this happens, or to write more complicated code that manually closes and re-creates the EventSource object if there is a connection error. I'm hopeful that this bug will be fixed.

    • Browser vendors have decided to not implement HTTP/2 without TLS. This means that each /esbuild event source will take up one of your precious 6 simultaneous per-domain HTTP/1.1 connections. So if you open more than six HTTP tabs that use this live-reloading technique, you will be unable to use live reloading in some of those tabs (and other things will likely also break). The workaround is to enable HTTPS, which is now possible to do in esbuild itself (see below).

  • Add built-in support for HTTPS (#​2169)

    You can now tell esbuild's built-in development server to use HTTPS instead of HTTP. This is sometimes necessary because browser vendors have started making modern web features unavailable to HTTP websites. Previously you had to put a proxy in front of esbuild to enable HTTPS since esbuild's development server only supported HTTP. But with this release, you can now enable HTTPS with esbuild without an additional proxy.

    To enable HTTPS with esbuild:

    1. Generate a self-signed certificate. There are many ways to do this. Here's one way, assuming you have openssl installed:

      openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 9999 -nodes -subj /CN=127.0.0.1
      
    2. Add --keyfile=key.pem and --certfile=cert.pem to your esbuild development server command

    3. Click past the scary warning in your browser when you load your page

    If you have more complex needs than this, you can still put a proxy in front of esbuild and use that for HTTPS instead. Note that if you see the message "Client sent an HTTP request to an HTTPS server" when you load your page, then you are using the incorrect protocol. Replace http:// with https:// in your browser's URL bar.

    Keep in mind that esbuild's HTTPS support has nothing to do with security. The only reason esbuild now supports HTTPS is because browsers have made it impossible to do local development with certain modern web features without jumping through these extra hoops. Please do not use esbuild's development server for anything that needs to be secure. It's only intended for local development and no considerations have been made for production environments whatsoever.

  • Better support copying index.html into the output directory (#​621, #​1771)

    Right now esbuild only supports JavaScript and CSS as first-class content types. Previously this meant that if you were building a website with a HTML file, a JavaScript file, and a CSS file, you could use esbuild to build the JavaScript file and the CSS file into the output directory but not to copy the HTML file into the output directory. You needed a separate cp command for that.

    Or so I thought. It turns out that the copy loader added in version 0.14.44 of esbuild is sufficient to have esbuild copy the HTML file into the output directory as well. You can add something like index.html --loader:.html=copy and esbuild will copy index.html into the output directory for you. The benefits of this are a) you don't need a separate cp command and b) the index.html file will automatically be re-copied when esbuild is in watch mode and the contents of index.html are edited. This also goes for other non-HTML file types that you might want to copy.

    This pretty much already worked. The one thing that didn't work was that esbuild's built-in development server previously only supported implicitly loading index.html (e.g. loading /about/index.html when you visit /about/) when index.html existed on the file system. Previously esbuild didn't support implicitly loading index.html if it was a build result. That bug has been fixed with this release so it should now be practical to use the copy loader to do this.

  • Fix onEnd not being called in serve mode (#​1384)

    Previous releases had a bug where plugin onEnd callbacks weren't called when using the top-level serve() API. This API no longer exists and the internals have been reimplemented such that onEnd callbacks should now always be called at the end of every build.

  • Incremental builds now write out build results differently (#​2104)

    Previously build results were always written out after every build. However, this could cause the output directory to fill up with files from old builds if code splitting was enabled, since the file names for code splitting chunks contain content hashes and old files were not deleted.

    With this release, incremental builds in esbuild will now delete old output files from previous builds that are no longer relevant. Subsequent incremental builds will also no longer overwrite output files whose contents haven't changed since the previous incremental build.

  • The onRebuild watch mode callback was removed (#​980, #​2499)

    Previously watch mode accepted an onRebuild callback which was called whenever watch mode rebuilt something. This was not great in practice because if you are running code after a build, you likely want that code to run after every build, not just after the second and subsequent builds. This release removes option to provide an onRebuild callback. You can create a plugin with an onEnd callback instead. The onEnd plugin API already exists, and is a way to run some code after every build.

  • You can now return errors from onEnd (#​2625)

    It's now possible to add additional build errors and/or warnings to the current build from within your onEnd callback by returning them in an array. This is identical to how the onStart callback already works. The evaluation of onEnd callbacks have been moved around a bit internally to make this possible.

    Note that the build will only fail (i.e. reject the promise) if the additional errors are returned from onEnd. Adding additional errors to the result object that's passed to onEnd won't affect esbuild's behavior at all.

  • Print URLs and ports from the Go and JS APIs (#​2393)

    Previously esbuild's CLI printed out something like this when serve mode is active:

     > Local:   http://127.0.0.1:8000/
     > Network: http://192.168.0.1:8000/
    

    The CLI still does this, but now the JS and Go serve mode APIs will do this too. This only happens when the log level is set to verbose, debug, or info but not when it's set to warning, error, or silent.

Upgrade guide for existing code:
  • Rebuild (a.k.a. incremental build):

    Before:

    const result = await esbuild.build({ ...buildOptions, incremental: true });
    builds.push(result);
    for (let i = 0; i < 4; i++) builds.push(await result.rebuild());
    await result.rebuild.dispose(); // To free resources

    After:

    const ctx = await esbuild.context(buildOptions);
    for (let i = 0; i < 5; i++) builds.push(await ctx.rebuild());
    await ctx.dispose(); // To free resources

    Previously the first build was done differently than subsequent builds. Now both the first build and subsequent builds are done using the same API.

  • Serve:

    Before:

    const serveResult = await esbuild.serve(serveOptions, buildOptions);
    ...
    serveResult.stop(); await serveResult.wait; // To free resources

    After:

    const ctx = await esbuild.context(buildOptions);
    const serveResult = await ctx.serve(serveOptions);
    ...
    await ctx.dispose(); // To free resources
  • Watch:

    Before:

    const result = await esbuild.build({ ...buildOptions, watch: true });
    ...
    result.stop(); // To free resources

    After:

    const ctx = await esbuild.context(buildOptions);
    await ctx.watch();
    ...
    await ctx.dispose(); // To free resources
  • Watch with onRebuild:

    Before:

    const onRebuild = (error, result) => {
      if (error) console.log('subsequent build:', error);
      else console.log('subsequent build:', result);
    };
    try {
      const result = await esbuild.build({ ...buildOptions, watch: { onRebuild } });
      console.log('first build:', result);
      ...
      result.stop(); // To free resources
    } catch (error) {
      console.log('first build:', error);
    }

    After:

    const plugins = [{
      name: 'my-plugin',
      setup(build) {
        let count = 0;
        build.onEnd(result => {
          if (count++ === 0) console.log('first build:', result);
          else console.log('subsequent build:', result);
        });
      },
    }];
    const ctx = await esbuild.context({ ...buildOptions, plugins });
    await ctx.watch();
    ...
    await ctx.dispose(); // To free resources

    The onRebuild function has now been removed. The replacement is to make a plugin with an onEnd callback.

    Previously onRebuild did not fire for the first build (only for subsequent builds). This was usually problematic, so using onEnd instead of onRebuild is likely less error-prone. But if you need to emulate the old behavior of onRebuild that ignores the first build, then you'll need to manually count and ignore the first build in your plugin (as demonstrated above).

Notice how all of these API calls are now done off the new context object. You should now be able to use all three kinds of incremental builds (rebuild, serve, and watch) together on the same context object. Also notice how calling dispose on the context is now the common way to discard the context and free resources in all of these situations.

v0.16.17

Compare Source

  • Fix additional comment-related regressions (#​2814)

    This release fixes more edge cases where the new comment preservation behavior that was added in 0.16.14 could introduce syntax errors. Specifically:

    x = () => (/* comment */ {})
    for ((/* comment */ let).x of y) ;
    function *f() { yield (/* comment */class {}) }

    These cases caused esbuild to generate code with a syntax error in version 0.16.14 or above. These bugs have now been fixed.

v0.16.16

Compare Source

  • Fix a regression caused by comment preservation (#​2805)

    The new comment preservation behavior that was added in 0.16.14 introduced a regression where comments in certain locations could cause esbuild to omit certain necessary parentheses in the output. The outermost parentheses were incorrectly removed for the following syntax forms, which then introduced syntax errors:

    (/* comment */ { x: 0 }).x;
    (/* comment */ function () { })();
    (/* comment */ class { }).prototype;

    This regression has been fixed.

v0.16.15

Compare Source

  • Add format to input files in the JSON metafile data

    When --metafile is enabled, input files may now have an additional format field that indicates the export format used by this file. When present, the value will either be cjs for CommonJS-style exports or esm for ESM-style exports. This can be useful in bundle analysis.

    For example, esbuild's new Bundle Size Analyzer now uses this information to visualize whether ESM or CommonJS was used for each directory and file of source code (click on the CJS/ESM bar at the top).

    This information is helpful when trying to reduce the size of your bundle. Using the ESM variant of a dependency instead of the CommonJS variant always results in a faster and smaller bundle because it omits CommonJS wrappers, and also may result in better tree-shaking as it allows esbuild to perform tree-shaking at the statement level instead of the module level.

  • Fix a bundling edge case with dynamic import (#​2793)

    This release fixes a bug where esbuild's bundler could produce incorrect output. The problematic edge case involves the entry point importing itself using a dynamic import() expression in an imported file, like this:

    // src/a.js
    export const A = 42;
    
    // src/b.js
    export const B = async () => (await import(".")).A
    
    // src/index.js
    export * from "./a"
    export * from "./b"
  • Remove new type syntax from type declarations in the esbuild package (#​2798)

    Previously you needed to use TypeScript 4.3 or newer when using the esbuild package from TypeScript code due to the use of a getter in an interface in node_modules/esbuild/lib/main.d.ts. This release removes this newer syntax to allow people with versions of TypeScript as far back as TypeScript 3.5 to use this latest version of the esbuild package. Here is change that was made to esbuild's type declarations:

     export interface OutputFile {
       /** "text" as bytes */
       contents: Uint8Array;
       /** "contents" as text (changes automatically with "contents") */
    -  get text(): string;
    +  readonly text: string;
     }

v0.16.14

Compare Source

  • Preserve some comments in expressions (#​2721)

    Various tools give semantic meaning to comments embedded inside of expressions. For example, Webpack and Vite have special "magic comments" that can be used to affect code splitting behavior:

    import(/* webpackChunkName: "foo" */ '../foo');
    import(/* @&#8203;vite-ignore */ dynamicVar);
    new Worker(/* webpackChunkName: "bar" */ new URL("../bar.ts", import.meta.url));
    new Worker(new URL('./path', import.meta.url), /* @&#8203;vite-ignore */ dynamicOptions);

    Since esbuild can be used as a preprocessor for these tools (e.g. to strip TypeScript types), it can be problematic if esbuild doesn't do additional work to try to retain these comments. Previously esbuild special-cased Webpack comments in these specific locations in the AST. But Vite would now like to use similar comments, and likely other tools as well.

    So with this release, esbuild now will attempt to preserve some comments inside of expressions in more situations than before. This behavior is mainly intended to preserve these special "magic comments" that are meant for other tools to consume, although esbuild will no longer only preserve Webpack-specific comments so it should now be tool-agnostic. There is no guarantee that all such comments will be preserved (especially when --minify-syntax is enabled). So this change does not mean that esbuild is now usable as a code formatter. In particular comment preservation is more likely to happen with leading comments than with trailing comments. You should put comments that you want to be preserved before the relevant expression instead of after it. Also note that this change does not retain any more statement-level comments than before (i.e. comments not embedded inside of expressions). Comment preservation is not enabled when --minify-whitespace is enabled (which is automatically enabled when you use --minify).

v0.16.13

Compare Source

  • Publish a new bundle visualization tool

    While esbuild provides bundle metadata via the --metafile flag, previously esbuild left analysis of it completely up to third-party tools (well, outside of the rudimentary --analyze flag). However, the esbuild website now has a built-in bundle visualization tool:

    You can pass --metafile to esbuild to output bundle metadata, then upload that JSON file to this tool to visualize your bundle. This is helpful for answering questions such as:

    • Which packages are included in my bundle?
    • How did a specific file get included?
    • How small did a specific file compress to?
    • Was a specific file tree-shaken or not?

    I'm publishing this tool because I think esbuild should provide some answer to "how do I visualize my bundle" without requiring people to reach for third-party tools. At the moment the tool offers two types of visualizations: a radial "sunburst chart" and a linear "flame chart". They serve slightly different but overlapping use cases (e.g. the sunburst chart is more keyboard-accessible while the flame chart is easier with the mouse). This tool may continue to evolve over time.

  • Fix --metafile and --mangle-cache with --watch (#​1357)

    The CLI calls the Go API and then also writes out the metafile and/or mangle cache JSON files if those features are enabled. This extra step is necessary because these files are returned by the Go API as in-memory strings. However, this extra step accidentally didn't happen for all builds after the initial build when watch mode was enabled. This behavior used to work but it was broken in version 0.14.18 by the introduction of the mangle cache feature. This release fixes the combination of these features, so the metafile and mangle cache features should now work with watch mode. This behavior was only broken for the CLI, not for the JS or Go APIs.

  • Add an original field to the metafile

    The metadata file JSON now has an additional field: each import in an input file now contains the pre-resolved path in the original field in addition to the post-resolved path in the path field. This means it's now possible to run certain additional analysis over your bundle. For example, you should be able to use this to detect when the same package subpath is represented multiple times in the bundle, either because multiple versions of a package were bundled or because a package is experiencing the dual-package hazard.

v0.16.12

Compare Source

  • Loader defaults to js for extensionless files (#​2776)

    Certain packages contain files without an extension. For example, the yargs package contains the file yargs/yargs which has no extension. Node, Webpack, and Parcel can all understand code that imports yargs/yargs because they assume that the file is JavaScript. However, esbuild was previously unable to understand this code because it relies on the file extension to tell it how to interpret the file. With this release, esbuild will now assume files without an extension are JavaScript files. This can be customized by setting the loader for "" (the empty string, representing files without an extension) to another loader. For example, if you want files without an extension to be treated as CSS instead, you can do that like this:

    • CLI:

      esbuild --bundle --loader:=css
      
    • JS:

      esbuild.build({
        bundle: true,
        loader: { '': 'css' },
      })
    • Go:

      api.Build(api.BuildOptions{
        Bundle: true,
        Loader: map[string]api.Loader{"": api.LoaderCSS},
      })

    In addition, the "type" field in package.json files now only applies to files with an explicit .js, .jsx, .ts, or .tsx extension. Previously it was incorrectly applied by esbuild to all files that had an extension other than .mjs, .mts, .cjs, or .cts including extensionless files. So for example an extensionless file in a "type": "module" package is now treated as CommonJS instead of ESM.

v0.16.11

Compare Source

  • Avoid a syntax error in the presence of direct eval (#​2761)

    The behavior of nested function declarations in JavaScript depends on whether the code is run in strict mode or not. It would be problematic if esbuild preserved nested function declarations in its output because then the behavior would depend on whether the output was run in strict mode or not instead of respecting the strict mode behavior of the original source code. To avoid this, esbuild transforms nested function declarations to preserve the intended behavior of the original source code regardless of whether the output is run in strict mode or not:

    // Original code
    if (true) {
      function foo() {}
      console.log(!!foo)
      foo = null
      console.log(!!foo)
    }
    console.log(!!foo)
    
    // Transformed code
    if (true) {
      let foo2 = function() {
      };
      var foo = foo2;
      console.log(!!foo2);
      foo2 = null;
      console.log(!!foo2);
    }
    console.log(!!foo);

    In the above example, the original code should print true false true because it's not run in strict mode (it doesn't contain "use strict" and is not an ES module). The code that esbuild generates has been transformed such that it prints true false true regardless of whether it's run in strict mode or not.

    However, this transformation is impossible if the code contains direct eval because direct eval "poisons" all containing scopes by preventing anything in those scopes from being renamed. That prevents esbuild from splitting up accesses to foo into two separate variables with different names. Previously esbuild still did this transformation but with two variables both named foo, which is a syntax error. With this release esbuild will now skip doing this transformation when direct eval is present to avoid generating code with a syntax error. This means that the generated code may no longer behave as intended since the behavior depends on the run-time strict mode setting instead of the strict mode setting present in the original source code. To fix this problem, you will need to remove the use of direct eval.

  • Fix a bundling scenario involving multiple symlinks (#​2773, #​2774)

    This release contains a fix for a bundling scenario involving an import path where multiple path segments are symlinks. Previously esbuild was unable to resolve certain import paths in this scenario, but these import paths should now work starting with this release. This fix was contributed by @​onebytegone.

v0.16.10

Compare Source

  • Change the default "legal comment" behavior again (#​2745)

    The legal comments feature automatically gathers comments containing @license or @preserve and puts the comments somewhere (either in the generated code or in a separate file). This behavior used to be on by default but was disabled by default in version 0.16.0 because automatically inserting comments is potentially confusing and misleading. These comments can appear to be assigning the copyright of your code to another entity. And this behavior can be especially problematic if it happens automatically by default since you may not even be aware of it happening. For example, if you bundle the TypeScript compiler the preserving legal comments means your source code would contain this comment, which appears to be assigning the copyright of all of your code to Microsoft:

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation. All rights reserved.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
    this file except in compliance with the License. You may obtain a copy of the
    License at http://www.apache.org/licenses/LICENSE-2.0
    
    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
    MERCHANTABLITY OR NON-INFRINGEMENT.
    
    See the Apache Version 2.0 License for specific language governing permissions
    and limitations under the License.
    ***************************************************************************** */

    However, people have asked for this feature to be re-enabled by default. To resolve the confusion about what these comments are applying to, esbuild's default behavior will now be to attempt to describe which package the comments are coming from. So while this feature has been re-enabled by default, the output will now look something like this instead:

    /*! Bundled license information:
    
    typescript/lib/typescript.js:
      (*! *****************************************************************************
      Copyright (c) Microsoft Corporation. All rights reserved.
      Licensed under the Apache License, Version 2.0 (the "License"); you may not use
      this file except in compliance with the License. You may obtain a copy of the
      License at http://www.apache.org/licenses/LICENSE-2.0
    
      THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
      KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
      WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
      MERCHANTABLITY OR NON-INFRINGEMENT.
    
      See the Apache Version 2.0 License for specific language governing permissions
      and limitations under the License.
      ***************************************************************************** *)
    */

    Note that you can still customize this behavior with the --legal-comments= flag. For example, you can use --legal-comments=none to turn this off, or you can use --legal-comments=linked to put these comments in a separate .LEGAL.txt file instead.

  • Enable external legal comments with the transform API (#​2390)

    Previously esbuild's transform API only supported none, inline, or eof legal comments. With this release, external legal comments are now also supported with the transform API. This only applies to the JS and Go APIs, not to the CLI, and looks like this:

    • JS:

      const { code, legalComments } = await esbuild.transform(input, {
        legalComments: 'external',
      })
    • Go:

      result := api.Transform(input, api.TransformOptions{
        LegalComments: api.LegalCommentsEndOfFile,
      })
      code := result.Code
      legalComments := result.LegalComments
  • Fix duplicate function declaration edge cases (#​2757)

    The change in the previous release to forbid duplicate function declarations in certain cases accidentally forbid some edge cases that should have been allowed. Specifically duplicate function declarations are forbidden in nested blocks in strict mode and at the top level of modules, but are allowed when they are declared at the top level of function bodies. This release fixes the regression by re-allowing the last case.

  • Allow package subpaths with alias (#​2715)

    Previously the names passed to the alias feature had to be the name of a package (with or without a package scope). With this release, you can now also use the alias feature with package subpaths. So for example you can now create an alias that substitutes @org/pkg/lib with something else.

v0.16.9

Compare Source

  • Update to Unicode 15.0.0

    The character tables that determine which characters form valid JavaScript identifiers have been updated from Unicode version 14.0.0 to the newly-released Unicode version 15.0.0. I'm not putting an example in the release notes because all of the new characters will likely just show up as little squares since fonts haven't been updated yet. But you can read https://www.unicode.org/versions/Unicode15.0.0/#Summary for more information about the changes.

  • Disallow duplicate lexically-declared names in nested blocks and in strict mode

    In strict mode or in a nested block, it's supposed to be a syntax error to declare two symbols with the same name unless all duplicate entries are either function declarations or all var declarations. However, esbuild was overly permissive and allowed this when duplicate entries were either function declarations or var declarations (even if they were mixed). This check has now been made more restrictive to match the JavaScript specification:

    // JavaScript allows this
    var a
    function a() {}
    {
      var b
      var b
      function c() {}
      function c() {}
    }
    
    // JavaScript doesn't allow this
    {
      var d
      function d() {}
    }
  • Add a type declaration for the new empty loader (#​2755)

    I forgot to add this in the previous release. It has now been added.

    This fix was contributed by @​fz6m.

  • Add support for the v flag in regular expression literals

    People are currently working on adding a v flag to JavaScript regular expresions. You can read more about this flag here: https://v8.dev/features/regexp-v-flag. This release adds support for parsing this flag, so esbuild will now no longer consider regular expression literals with this flag to be a syntax error. If the target is set to something other than esnext, esbuild will transform regular expression literals containing this flag into a new RegExp() constructor call so the resulting code doesn't have a syntax error. This enables you to provide a polyfill for RegExp that implements the v flag to get your code to work at run-time. While esbuild doesn't typically adopt proposals until they're already shipping in a real JavaScript run-time, I'm adding it now because a) esbuild's implementation doesn't need to change as the proposal evolves, b) this isn't really new syntax since regular expression literals already have flags, and c) esbuild's implementation is a trivial pass-through anyway.

  • Avoid keeping the name of classes with static name properties

    The --keep-names property attempts to preserve the original value of the name property for functions and classes even when identifiers are renamed by the minifier or to avoid a name collision. This is currently done by generating code to assign a string to the name property on the function or class object. However, this should not be done for classes with a static name property since in that case the explicitly-defined name property overwrites the automatically-generated class name. With this release, esbuild will now no longer attempt to preserve the name property for classes with a static name property.

v0.16.8

Compare Source

  • Allow plugins to resolve injected files (#​2754)

    Previously paths passed to the inject feature were always interpreted as file system paths. This meant that onResolve plugins would not be run for them and esbuild's default path resolver would always be used. This meant that the inject feature couldn't be used in the browser since the browser doesn't have access to a file system. This release runs paths passed to inject through esbuild's full path resolution pipeline so plugins now have a chance to handle them using onResolve callbacks. This makes it possible to write a plugin that makes esbuild's inject work in the browser.

  • Add the empty loader (#​1541, #​2753)

    The new empty loader tells esbuild to pretend that a file is empty. So for example --loader:.css=empty effectively skips all imports of .css files in JavaScript so that they aren't included in the bundle, since import "./some-empty-file" in JavaScript doesn't bundle anything. You can also use the empty loader to remove asset references in CSS files. For example --loader:.png=empty causes esbuild to replace asset references such as url(image.png) with url() so that they are no longer included in the resulting style sheet.

  • Fix </script> and </style> escaping for non-default targets (#​2748)

    The change in version 0.16.0 to give control over </script> escaping via --supported:inline-script=false or --supported:inline-script=true accidentally broke automatic escaping of </script> when an explicit target setting is specified. This release restores the correct automatic escaping of </script> (which should not depend on what target is set to).

  • Enable the exports field with NODE_PATHS (#​2752)

    Node has a rarely-used feature where you can extend the set of directories that node searches for packages using the NODE_PATHS environment variable. While esbuild supports this too, previously it only supported the old main field path resolution but did not support the new exports field package resolution. This release makes the path resolution rules the same again for both node_modules directories and NODE_PATHS directories.

v0.16.7

Compare Source

  • Include file loader strings in metafile imports (#​2731)

    Bundling a file with the file loader copies that file to the output directory and imports a module with the path to the copied file in the default export. Previously when bundling with the file loader, there was no reference in the metafile from the JavaScript file containing the path string to the copied file. With this release, there will now be a reference in the metafile in the imports array with the kind file-loader:

     {
       ...
       "outputs": {
         "out/image-55CCFTCE.svg": {
           ...
         },
         "out/entry.js": {
           "imports": [
    +        {
    +          "path": "out/image-55CCFTCE.svg",
    +          "kind": "file-loader"
    +        }
           ],
           ...
         }
       }
     }
  • Fix byte counts in metafile regarding references to other output files (#​2071)

    Previously files that contained references to other output files had slightly incorrect metadata for the byte counts of input files which contributed to that output file. So for example if app.js imports image.png using the file loader and esbuild generates out.js and image-LSAMBFUD.png, the metadata for how many bytes of out.js are from app.js was slightly off (the metadata for the byte count of out.js was still correct). The reason is because esbuild substitutes the final paths for references between output files toward the end of the build to handle cyclic references, and the byte counts needed to be adjusted as well during the path substitution. This release fixes these byte counts (specifically the bytesInOutput values).

  • The alias feature now strips a trailing slash (#​2730)

    People sometimes add a trailing slash to the name of one of node's built-in modules to force node to import from the file system instead of importing the built-in module. For example, importing util imports node's built-in module called util but importing util/ tries to find a package called util on the file system. Previously attempting to use esbuild's package alias feature to replace imports to util with a specific file would fail because the file path would also gain a trailing slash (e.g. mapping util to ./file.js turned util/ into ./file.js/). With this release, esbuild will now omit the path suffix if it's a single trailing slash, which should now allow you to successfully apply aliases to these import paths.

v0.16.6

Compare Source

  • Do not mark subpath imports as external with --packages=external (#​2741)

    Node has a feature called subpath imports where special import paths that start with # are resolved using the imports field in the package.json file of the enclosing package. The intent of the newly-added --packages=external setting is to exclude a package's dependencies from the bundle. Since a package's subpath imports are only accessible within that package, it's wrong for them to be affected by --packages=external. This release changes esbuild so that --packages=external no longer affects subpath imports.

  • Forbid invalid numbers in JSON files

    Previously esbuild parsed numbers in JSON files using the same syntax as JavaScript. But starting from this release, esbuild will now parse them with JSON syntax instead. This means the following numbers are no longer allowed by esbuild in JSON files:

    • Legacy octal literals (non-zero integers starting with 0)
    • The 0b, 0o, and 0x numeric prefixes
    • Numbers containing _ such as 1_000
    • Leading and trailing . such as 0. and .0
    • Numbers with a space after the - such as - 1
  • Add external imports to metafile (#​905, #​1768, #​1933, #​1939)

    External imports now appear in imports arrays in the metafile (which is present when bundling with metafile: true) next to normal imports, but additionally have external: true to set them apart. This applies both to files in the inputs section and the outputs section. Here's an example:

     {
       "inputs": {
         "style.css": {
           "bytes": 83,
           "imports": [
    +        {
    +          "path": "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css",
    +          "kind": "import-rule",
    +          "external": true
    +        }
           ]
         },
         "app.js": {
           "bytes": 100,
           "imports": [
    +        {
    +          "path": "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js",
    +          "kind": "import-statement",
    +          "external": true
    +        },
             {
               "path": "style.css",
               "kind": "import-statement"
             }
           ]
         }
       },
       "outputs": {
         "out/app.js": {
           "imports": [
    +        {
    +          "path": "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js",
    +          "kind": "require-call",
    +          "external": true
    +        }
           ],
           "exports": [],
           "entryPoint": "app.js",
           "cssBundle": "out/app.css",
           "inputs": {
             "app.js": {
               "bytesInOutput": 113
             },
             "style.css": {
               "bytesInOutput": 0
             }
           },
           "bytes": 528
         },
         "out/app.css": {
           "imports": [
    +        {
    +          "path": "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css",
    +          "kind": "import-rule",
    +          "external": true
    +        }
           ],
           "inputs": {
             "style.css": {
               "bytesInOutput": 0
             }
           },
           "bytes": 100
         }
       }
     }

    One additional useful consequence of this is that the imports array is now populated when bundling is disabled. So you can now use esbuild with bundling disabled to inspect a file's imports.

v0.16.5

Compare Source

  • Make it easy to exclude all packages from a bundle (#​1958, #​1975, #​2164, #​2246, #​2542)

    When bundling for node, it's often necessary to exclude npm packages from the bundle since they weren't designed with esbuild bundling in mind and don't work correctly after being bundled. For example, they may use __dirname and run-time file system calls to load files, which doesn't work after bundling with esbuild. Or they may compile a native .node extension that has similar expectations about the layout of the file system that are no longer true after bundling (even if the .node extension is copied next to the bundle).

    The way to get this to work with esbuild is to use the --external: flag. For example, the fsevents package contains a native .node extension and shouldn't be bundled. To bundle code that uses it, you can pass --external:fsevents to esbuild to exclude it from your bundle. You will then need to ensure that the fsevents package is still present when you run your bundle (e.g. by publishing your bundle to npm as a package with a dependency on fsevents).

    It was possible to automatically do this for all of your dependencies, but it was inconvenient. You had to write some code that read your package.json file and passed the keys of the dependencies, devDependencies, peerDependencies, and/or optionalDependencies maps to esbuild as external packages (either that or write a plugin to mark all package paths as external). Previously esbuild's recommendation for making this easier was to do --external:./node_modules/* (added in version 0.14.13). However, this was a bad idea because it caused compatibility problems with many node packages as it caused esbuild to mark the post-resolve path as external instead of the pre-resolve path. Doing that could break packages that are published as both CommonJS and ESM if esbuild's bundler is also used to do a module format conversion.

    With this release, you can now do the following to automatically exclude all packages from your bundle:

    • CLI:

      esbuild --bundle --packages=external
      
    • JS:

      esbuild.build({
        bundle: true,
        packages: 'external',
      })
    • Go:

      api.Build(api.BuildOptions{
        Bundle:   true,
        Packages: api.PackagesExternal,
      })

    Doing --external:./node_modules/* is still possible and still has the same behavior, but is no longer recommended. I recommend that you use the new packages feature instead.

  • Fix some subtle bugs with tagged template literals

    This release fixes a bug where minification could incorrectly change the value of this within tagged template literal function calls:

    // Original code
    function f(x) {
      let z = y.z
      return z``
    }
    
    // Old output (with --minify)
    function f(n){return y.z``}
    
    // New output (with --minify)
    function f(n){return(0,y.z)``}

    This release also fixes a bug where using optional chaining with --target=es2019 or earlier could incorrectly change the value of this within tagged template literal function calls:

    // Original code
    var obj = {
      foo: function() {
        console.log(this === obj);
      }
    };
    (obj?.foo)``;
    
    // Old output (with --target=es6)
    var obj = {
      foo: function() {
        console.log(this === obj);
      }
    };
    (obj == null ? void 0 : obj.foo)``;
    
    // New output (with --target=es6)
    var __freeze = Object.freeze;
    var __defProp = Object.defineProperty;
    var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
    var _a;
    var obj = {
      foo: function() {
        console.log(this === obj);
      }
    };
    (obj == null ? void 0 : obj.foo).call(obj, _a || (_a = __template([""])));
  • Some slight minification improvements

    The following minification improvements were implemented:

    • if (~a !== 0) throw x; => if (~a) throw x;
    • if ((a | b) !== 0) throw x; => if (a | b) throw x;
    • if ((a & b) !== 0) throw x; => if (a & b) throw x;
    • if ((a ^ b) !== 0) throw x; => if (a ^ b) throw x;
    • if ((a << b) !== 0) throw x; => if (a << b) throw x;
    • if ((a >> b) !== 0) throw x; => if (a >> b) throw x;
    • if ((a >>> b) !== 0) throw x; => if (a >>> b) throw x;
    • if (!!a || !!b) throw x; => if (a || b) throw x;
    • if (!!a && !!b) throw x; => if (a && b) throw x;
    • if (a ? !!b : !!c) throw x; => if (a ? b : c) throw x;

v0.16.4

Compare Source

  • Fix binary downloads from the @esbuild/ scope for Deno (#​2729)

    Version 0.16.0 of esbuild moved esbuild's binary executables into npm packages under the @esbuild/ scope, which accidentally broke the binary downloader script for Deno. This release fixes this script so it should now be possible to use esbuild version 0.16.4+ with Deno.

v0.16.3

Compare Source

  • Fix a hang with the JS API in certain cases (#​2727)

    A change that was made in version 0.15.13 accidentally introduced a case when using esbuild's JS API could cause the node process to fail to exit. The change broke esbuild's watchdog timer, which detects if the parent process no longer exists and then automatically exits esbuild. This hang happened when you ran node as a child process with the stderr stream set to pipe instead of inherit, in the child process you call esbuild's JS API and pass incremental: true but do not call dispose() on the returned rebuild object, and then call process.exit(). In that case the parent node process was still waiting for the esbuild process that was created by the child node process to exit. The change made in version 0.15.13 was trying to avoid using Go's sync.WaitGroup API incorrectly because the API is not thread-safe. Instead of doing this, I have now reverted that change and implemented a thread-safe version of the sync.WaitGroup API for esbuild to use instead.

v0.16.2

Compare Source

  • Fix process.env.NODE_ENV substitution when transforming (#​2718)

    Version 0.16.0 introduced an unintentional regression that caused process.env.NODE_ENV to be automatically substituted with either "development" or "production" when using esbuild's transform API. This substitution is a necessary feature of esbuild's build API because the React framework crashes when you bundle it without doing this. But the transform API is typically used as part of a larger build pipeline so the benefit of esbuild doing this automatically is not as clear, and esbuild previously didn't do this.

    However, version 0.16.0 switched the default value of the platform setting for the transform API from neutral to browser, both to align it with esbuild's documentation (which says browser is the default value) and because escaping the </script> character sequence is now tied to the browser platform (see the release notes for version 0.16.0 for details). That accidentally enabled automatic substitution of process.env.NODE_ENV because esbuild always did that for code meant for the browser. To fix this regression, esbuild will now only automatically substitute process.env.NODE_ENV when using the build API.

  • Prevent define from substituting constants into assignment position (#​2719)

    The define feature lets you replace certain expressions with constants. For example, you could use it to replace references to the global property reference window.DEBUG with false at compile time, which can then potentially help esbuild remove unused code from your bundle. It's similar to DefinePlugin in Webpack.

    However, if you write code such as window.DEBUG = true and then defined window.DEBUG to false, esbuild previously generated the output false = true which is a syntax error in JavaScript. This beha


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate. View repository job log here.

renovate bot and others added 2 commits January 14, 2023 06:19
Update generated files

Co-authored-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
@renovate
Copy link
Contributor Author

renovate bot commented Jan 16, 2023

Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.
You can manually request rebase by checking the rebase/retry box above.

Warning: custom changes will be lost.

@ajvpot ajvpot merged commit 9e64f15 into main Jan 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant