JLRishe
JLRishe

Reputation: 101662

Trouble using Babel external helpers with ES6 modules - Babel reordering imports/exports breaks execution order

I'm encountering an issue trying to use Babel's external helpers with ES6 modules, and wondering if I'm going about this the right way. As of now, I'm unable to get the transpiled code to run, as detailed below, but the tl;dr version is that Babel is reordering my imports and exports into an order that breaks the code, and I don't know why it's doing this.

Here is a very simplified example that demonstrates the issue:

source/index.js

// import babel helpers first so they are added to the global scope 
// and available to anything that needs them
import './babel-helpers';

export * from './dependency';

source/dependency.js

const constant = 'myProp';

const a = { [constant]: 1 };
const b = { [constant]: 2 };

export { a, b };

source/babel-helpers.js (autogenerated using babel-external-helpers -l defineProperty)

(function (global) {
  var babelHelpers = global.babelHelpers = {};

  babelHelpers.defineProperty = function (obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  };
})(typeof global === "undefined" ? self : global);

.babelrc

{
  "plugins": ["external-helpers"],
  "presets": ["env"]
}

After transpiling these with babel source --output-dir built, the output is:

built/index.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _dependency = require('./dependency');

Object.keys(_dependency).forEach(function (key) {
  if (key === "default" || key === "__esModule") return;
  Object.defineProperty(exports, key, {
    enumerable: true,
    get: function get() {
      return _dependency[key];
    }
  });
});

require('./babel-helpers');

built/dependency.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
var constant = 'myProp';

var a = babelHelpers.defineProperty({}, constant, 1);
var b = babelHelpers.defineProperty({}, constant, 2);

exports.a = a;
exports.b = b;

built/babel-helpers.js is not meaningfully changed from the original


The problem I'm having is that for some reason, the transpiled import './babel-helpers' is moved to the end of index.js, so when I try to run the code, it very understandably fails with an error because the code that uses the helpers runs before they are added to the global scope:

var a = babelHelpers.defineProperty({}, constant, 1);
        ^

ReferenceError: babelHelpers is not defined

If I manually edit the transpiled index.js to move require('./babel-helpers'); to the top of the file, the code runs fine.

So I have two questions:

  1. Why is Babel doing this strange reordering of imports and exports? It seems completely nonsensical. Is there a way to control it?
  2. Am I going about this the wrong way? Is there a better way to use external helpers? The documentation gives no guidance about what to actually do with the generated helpers. Generating them into a module and explicitly importing that module into every file that will ultimately need them would probably work, but that seems like a very WET way to go about things. Surely, it would be better for my individual modules to not have to explicitly refer to them in the pre-transpiled source.

I've created a Github repo of this scenario in case anyone would like to run it themselves: https://github.com/JLRishe/babel-helpers-e6-modules-issue

Upvotes: 1

Views: 1183

Answers (1)

JLRishe
JLRishe

Reputation: 101662

It turns out that the reordering of imports and exports is a bug that is fixed in Babel's 7.x beta:

https://github.com/babel/babel/issues/6468

I ended filing my own issue about this, and a Babel team member replied to point out that it was a known (fixed) issue. He also imparted some advice about the use of external helpers as it turns out importing them globally isn't such a good idea when writing a library:

https://github.com/babel/babel/issues/6919

Upvotes: 2

Related Questions