babelify: Incorrect export when using ES6 export syntax

Hi,

I’m currently making the switch to Babel 6 and running into the following problem, which might* be related to babelify.

Here’s my gulp-task:

let bify = browserify({
    entries    : './src/scripts/main.js',
    standalone : 'basicContext'
})

let transformer = babelify.configure({
    presets: ['es2015']
})

bify.transform(transformer)
    .bundle()
    .on('error', catchError)
    .pipe(source(name + '.min.js'))
    .pipe(buffer())
    .pipe(plugins.uglify())
    .on('error', catchError)
    .pipe(gulp.dest('./dist'))

main.js exports a function:

export default function(e, items, opts = {}) { … }

As I’m bundling this file as a standalone UMD module, I expected the variable basicContext to be a function. This was the case before I updated babelify and babel. Now basicContext is the following:

console.log(basicContext)
// {__esModule: true, default: function}

Best Tobias

  • Could be cased by Babel 6, too. It’s really not easy to find the dependency casing the issue.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 20 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Also, for those of you interested, this is my terrible hack to change thi behavior in my gulp pipeline:

.pipe(replace("exports.default = MyFunction;", "module.exports = MyFunction;"))

I just wanted to follow up and say this only seems to be an issue when using Babel and requiring ES6 modules inside of ES5 modules. Just now made that realization, sorry for the noise :\

I just ran into this when upgrading to 7.2. From my understanding, after this update, the correct way to import ES6 modules is something like this:

import {default as Foo} from 'foo';

where Foo is the following:

class Foo extends React.Component {
    ...
}

export default Foo;

Am I way off base here or is this the preference moving forward? I’d appreciate any help on this.

I now understand why it still works in other projects. Here’s a quick example:

Exporting the following and packaging it as a standalone UMD module using browserify …

export const a = function() { … }
export const b = function() { … }

… will produce the following output:

{__esModule: true, a: function, b: function, …}

As I’m calling the functions using moduleName.a and moduleName.b, everything works fine. However, when using export default the produced object will contains a default property. Calling the function using moduleName() won’t work. I had to use moduleName.default() instead.

The reason for this—and correct me if I’m wrong—is the fact that you can use both export and export default inside a single module. That’s not possible in CommonJS. The added default property is a workaround to make both “compatible”.

@electerious It’s not really the export that’s the problem. That is the best you can do with ES2015 module syntax. It’s a design change in what Babel compiles it to and what that means for CommonJS interop. You have a few options (at least):

  • Just write ES5 CJS (like @zertosh suggested): module.exports = function () {}.
  • Split your module in 2: keep your ES2015 module and make a new main.js that does module.exports = require("real-main").default;.
  • Make your main.js a stream that does that, if you want to avoid creating a new physical file (e.g. stream.end('module.exports = require("main").default'); browserify(stream);
  • Create a transform that adds something like this to main.js: module.exports = exports.default; Object.keys(exports.default).forEach(function (key) { return if (key !== "default") module.exports[key] = exports[key]; });