babel-plugin-transform-commonjs icon indicating copy to clipboard operation
babel-plugin-transform-commonjs copied to clipboard

IIFE transformed modules are incompatible es module babel plugins

Open gabemeola opened this issue 4 years ago • 4 comments

IIFE transformed modules are incompatible with babel plugins which transform es modules.

Sort of a mouthful but I'll try to explain what's happening below.

Consider this CJS module

this.name = 'true';

Running this through transform-commonjs wraps it in a IIFE to preserve the this module context.

var module = {
  exports: {}
};
var exports = module.exports;
(function () {
  this.name = 'true';
}).call(module.exports);
export default module.exports;

If we use another ESM babel transform (such as transform-modules-systemjs) it causes nested duplication of code

System.register([], function (_export2, _context) {
  "use strict";

  return {
    setters: [],
    execute: function () {
      System.register([], function (_export, _context) {
        "use strict";

        var module, exports;
        return {
          setters: [],
          execute: function () {
            module = {
              exports: {}
            };
            exports = module.exports;
            (function () {
              this.name = 'true';
            }).call(module.exports);

            _export("default", module.exports);
          }
        };
      });
    }
  };
});

BABEL REPL


The issue seems to be coming from this line in the ThisExpression branch: https://github.com/tbranyen/babel-plugin-transform-commonjs/blob/6b3ac9bf0870a995b67d3d93f60735ce798f3950/lib/index.ts#L62

I'm not too familiar with babel's helper functions. What's your thoughts on this? Is there another method which will prevent duplication of the program?

gabemeola avatar Oct 24 '19 18:10 gabemeola

Is the nested duplication breaking anything, or does it just look inefficient?

tbranyen avatar Oct 25 '19 02:10 tbranyen

For SystemJS in this case, it breaks dependency loading since the System.register call is duplicated.

gabemeola avatar Oct 31 '19 21:10 gabemeola

I use multi-pass to solve this problem. babel.transformFile + babel.transformAst.

shrinktofit avatar Nov 04 '19 03:11 shrinktofit

Replacing top level this exports with the exports keyword worked for me. https://github.com/tbranyen/babel-plugin-transform-commonjs/pull/16/files#diff-13b5b151431c7e7a17f273559ed212d5R316

Although this implementation may not cover all use cases and doesn't handle early returns

gabemeola avatar Nov 19 '19 15:11 gabemeola