Search code examples
javascriptimportexportdefault

Resolving compiled default exports with ES6 syntax


I have a module, say as follows:

const awesomeFn = () => ...

export default awesomeFn;

It is built into ES5 using babel, and when I created another ES6 module, I want the following syntax:

npm i awesomeFn

// ./index.js
import awesomeFn from 'awesomeFn';

awesomeFn();

But this throws. Logging awesomeFn gives me { default: _default [Function()] } (or something like that), hinting that I'd need to do something like

import awesomeFnPackage from 'awesomeFn';
const { default: awesomeFn } = awesomeFnPackage;

How can I form my exports so that I don't have to do the default destructuring? Should I avoid default exports altogether for this reason?


Somewhat strangely, this works if:

  • I use esm, like so node -r esm index.js but not if I use mjs as the file extension (with "type": "module" set), only js
  • It doesn't work with --experimental-modules, --experimental-specifier-resolution=node nor "type": "module" in package.json,
  • In every non-working case, the import value is { default: [Function: awesomeFn] }, only with esm is the value [Function: awesomeFn]

So I guess that's the solution right now; rely on an external package for expected behaviour, or use named exports, which do work as expected. What is going on with this?


Solution

  • Solution provided here, which is to destructure the default property as stated in the question, or add yet another dependency to intuitively use es6 imports.

    I'll leave out the reasoning for why this choice was made by Babel to the reader to research for brevity. My conclusion is to use ES5 or not to use default exports. ES6 syntax is a mess in the context of import/exports as of writing, not only in the context of this question, but in the context of npm packaging, file extensions, flags, package.json properties, etc.