3

I have a project that is using babel-register to dynamically transpile ES6 source to ES5 when requiring that module in a Node 6.6 project. I've read that babel-register hooks into Node's require function in order to transpile a file when you try to load it, but I'm not always clear on which files will be affected by that change.

This question comes up for me a lot when I'm writing tests: is only my production code getting transpiled, or does the test code get transpiled too?This brings me to the more general question, which is the topic of this post:

How can I tell when Babel is actually running, and which files are being transpiled?

Example code

Let's say I have production classes like this that are written in ES6 syntax

//src/greeter.js
export default class Greeter {
  sayHello() {
    return 'Hello World';
  }
}

and Babel is configured to transpile as so (.babelrc)

{
  "presets": ["es2015"]
}

and then there's some test code

//features/step_definitions/greeter_steps.js
import Greeter from '../../src/greeter'; //Causes greeter.js to be transpiled
import expect from 'expect';

var stepWrapper = function() {
  //Does Babel try to transpile this code too?
  this.Given(/^a greeter$/, function() { 
    this.greeter = new Greeter();
  });

  this.When(/^I ask it for a general greeting$/, function() {
    this.greeting = this.greeter.sayHello();
  });

  this.Then(/^it should greet the entire world$/, function() {
    expect(this.greeting).toEqual('Hello World');
  });
};

module.exports = stepWrapper;

and all of that runs on Node like so

cucumberjs --compiler js:babel-core/register

Example code is available here, if that is helpful.

Kyle Krull
  • 1,618
  • 2
  • 18
  • 25

2 Answers2

1

I made a hack to node_modules/babel-register/lib/node.js to do some logging like so

function compile(filename) {
  var result = void 0;

  var opts = new _babelCore.OptionManager().init((0, _extend2.default)({ sourceRoot: _path2.default.dirname(filename) }, (0, _cloneDeep2.default)(transformOpts), { filename: filename }));

  var cacheKey = (0, _stringify2.default)(opts) + ":" + babel.version;

  var env = process.env.BABEL_ENV || process.env.NODE_ENV;
  console.log('[babel-register::compile] filename=' + filename + '\n'); //Added logging here
  if (env) cacheKey += ":" + env;

  if (cache) {
    var cached = cache[cacheKey];
    if (cached && cached.mtime === mtime(filename)) {
      result = cached;
    }
  }
  ...
}

which then reports that test and production code are at least passing through Babel on some level

$ npm t

> cucumber-js-babel@1.0.0 test /Users/krull/git/sandbox/node/cucumber-js-babel
> cucumberjs --compiler js:babel-core/register

[babel-register::compile] filename=.../node/cucumber-js-babel/features/step_definitions/greeter_steps.js

[babel-register::compile] filename=.../node/cucumber-js-babel/src/greeter.js
...test results...

However, I'm hoping for a better solution that

  • works by some means of plugins and/or configuration, instead of monkey patching
  • better distinguishes which files are actually being transpiled, and which ones pass through Babel without modification
Kyle Krull
  • 1,618
  • 2
  • 18
  • 25
1

Because of this:

cucumberjs --compiler js:babel-core/register

...babel is invoked for both your test and regular source code. Keep in mind that in node, the only way to import JS is through require, so obviously babel-register will always be invoked. Of course, what babel does depends on its configuration, but most likely you have a simple configuration where all files required by require except those under node_modules will be transpiled.

Jacob
  • 77,566
  • 24
  • 149
  • 228