start start - 3 months ago 11
Javascript Question

Is my "import" statement being incorrectly transpiled?

It is my understanding that the following two lines are equivalent:

const Up = require('write-up').default


And...

import Up from 'write-up'


Both examples should make the default export of the
write-up
module available as
Up
.

Unfortunately, using Babel and Webpack, that's not the behavior I'm seeing.

The first example works just fine. It produces this line:

var Up = __webpack_require__(5).default;


Up
is set to the default export of the
write-up
module, which is the behavior I expect.

The second example does not work. It produces this:

var _writeUp = __webpack_require__(5);

var _writeUp2 = _interopRequireDefault(_writeUp);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }


Instead of setting
Up
to the default export,
Up
is set to an object containing every single export of the
write-up
module.
Up
even has a
default
field.
(The
write-up
module also has named exports, but this still occurs when I remove all of them.)

What am I doing wrong?

Here's the relevant portion from my Webpack config:

{
test: /.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015']
}
}

Answer

Babel-compiled import statements have a dual behavior. If the module being imported was compiled from ES6 export statements with Babel, then

import foo from 'foo';

will behave (mostly) like

const foo = require('foo').default;

but if foo was not compiled with Babel, or something that tries to be compatible with Babel, then as far as Babel is concerned, it has no special behavior and is a normal CommonJS module. In that case, which appears to be your case, it will behave like

const foo = require('foo');

Babel does this so that you can import normal CommonJS modules like

import fs from 'fs';

where fs is a standard Node module and has no .default property.

Comments