webpack: @swc/helpers is incorrectly removed/tree shaked from the production bundle

Bug report

What is the current behavior?

When using swc-loader with @swc/helpers and mixing ESM and CommonJS it seems that the tree shaking process in webpack incorrectly marks @swc/helpers as not used. When changing the repro below to only use ESM I can no longer reproduce it.

My first instinct was that this was an SWC issue and not a webpack issue, but from what I can tell SWC correcty determines the module type and injects import statements into ESM code and require statements into the CJS code.

Injected into ESM:

import _create_class from "@swc/helpers/src/_create_class.mjs";

Into CJS:

var _create_class = require("@swc/helpers").create_class;

If the current behavior is a bug, please provide the steps to reproduce.

I’ve created a small repro here: https://github.com/andersekdahl/webpack-swc-helpers-repro

entry.js:

import common from "./common";
import esm from "./esm";
console.log(common, esm);

common.js:

const x = class {
  method() {}
};

console.log(x);

module.exports = "commonjs";

esm.js:

const x = class {
  method() {}
};

console.log(x);

export default "esm";

webpack.config.js:

module.exports = {
  entry: "./src/entry.js",
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: "swc-loader",
          options: {
            jsc: {
              externalHelpers: true,
            },
            isModule: "unknown",
          },
        },
      },
    ],
  },
};

Prettified final bundle:

(() => {
  var e = {
      915: (e, r, o) => {
        var n = o(835).class_call_check,
          t = o(835).create_class,
          a = (function () {
            "use strict";
            function e() {
              n(this, e);
            }
            return t(e, [{ key: "method", value: function () {} }]), e;
          })();
        console.log(a), (e.exports = "commonjs");
      },
      835: () => {},
    },
    r = {};
  function o(n) {
    var t = r[n];
    if (void 0 !== t) return t.exports;
    var a = (r[n] = { exports: {} });
    return e[n](a, a.exports, o), a.exports;
  }
  (o.n = (e) => {
    var r = e && e.__esModule ? () => e.default : () => e;
    return o.d(r, { a: r }), r;
  }),
    (o.d = (e, r) => {
      for (var n in r)
        o.o(r, n) &&
          !o.o(e, n) &&
          Object.defineProperty(e, n, { enumerable: !0, get: r[n] });
    }),
    (o.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)),
    (() => {
      "use strict";
      var e = o(915),
        r = o.n(e);
      function n(e, r) {
        for (var o = 0; o < r.length; o++) {
          var n = r[o];
          (n.enumerable = n.enumerable || !1),
            (n.configurable = !0),
            "value" in n && (n.writable = !0),
            Object.defineProperty(e, n.key, n);
        }
      }
      var t = (function () {
        function e() {
          !(function (e, r) {
            if (!(e instanceof r))
              throw new TypeError("Cannot call a class as a function");
          })(this, e);
        }
        var r, o;
        return (
          (r = e),
          (o = [{ key: "method", value: function () {} }]) && n(r.prototype, o),
          e
        );
      })();
      console.log(t), console.log(r(), "esm");
    })();
})();

Note in the final bundle that module id 835 has an empty function that doesn’t return the exports create_class and class_call_check as expected.

What is the expected behavior?

That the needed exports from @swc/helpers are still in the final production bundle.

Other relevant information: webpack version: 5.76.3 Node.js version: Tested on 18.13.0 and 16.19.1 Operating System: Tested on Windows and Ubuntu Additional tools:

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

I can confirm that the latest version of @swc/core and @swc/helpers fixes the issue, thank you! I must have made a mistake somehow when trying to see if patching @swc/helpers would fix the issue. Thanks!

The new @swc/core with new @swc/helpers@0.5.0 is published. Could you try with the new version?