88
votes

In Babel 5.x, I can write the following code:

app.js

export default function (){}

index.js

require('babel/register');
require('./app')();

Then, I can run node index.js with no errors. However, using Babel 6.x, running the following code

index.es6.js

require('babel-core/register');
require('./app')();

results in an error

require(...) is not a function

I want to know why?

3
Do you have a .babelrc? Are you specifying Babel options somewhere? I ask because Babel 6 doesn't transpile anything by default and you are not specifying the es2015 preset in the code you have posted. - Igor Raush
@IgorRaush I really have a .babelrc, the others es6 script is running normally - XGHeaven
Please read the tag descriptions. babel is for questions for a Python library with said name. - Felix Kling
Just don't export a function from app.js, but run it right away - Bergi
@FelixKling sorry, I don't know the same name also in python... - XGHeaven

3 Answers

161
votes

TL;DR

You have to use

require('./app').default();

Explanation

Babel 5 used to have a compatibility hack for export default: if a module contained only one export, and it was a default export, it was assigned to module.exports. So, for example, your module app.js

export default function () {}

would be transpiled to this

"use strict";

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

exports["default"] = function () {};

module.exports = exports["default"];

This was done purely for compatibility with require-ing Babel-transpiled modules (like you are doing). It was also inconsistent; if a module contained both named and default exports, it could not be require-d.

In reality, according to the ES6 module spec, a default export is no different than a named export with the name default. It is just syntactic sugar which can be statically resolved at compile time, so this

import something from './app';

is the same as this

import { default as something } from './app';

That being said, it appears that Babel 6 decided to drop the interoperability hack when transpiling modules. Now, your module app.js is transpiled as

'use strict';

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

exports.default = function () {};

As you see, no more assignment to module.exports. To require this module, you need to do

require('./app').default();
7
votes

Just to follow up with the correct answer above.

If you wanna use default export behavior of babel@5, you can try babel-plugin-add-module-exports plugin.

It's working pretty well for me.

3
votes

If this doesn't work

require('./app').default()

use

require('./app').default

Without the function call at the end.