Patrick Roberts
Patrick Roberts

Reputation: 51946

Disadvantage of ES6 and CommonJS export convention

For the main file of an npm module, as defined by the package.json, I was considering a pattern like this:

import Struct from './src/struct'

module.exports = Struct
module.exports.default = Struct

In order to support both CommonJS and ES6 imports:

const Struct = require('my-module')
// or
import Struct from 'my-module'

Are there any downsides to this convention that might cause unintended problems?

The issue I'm trying to address is having to force consumers of the package to stick to ES6 or CommonJS because both of these seem rather unsavory:

const Struct = require('my-module').default
// or
import * as Struct from 'my-module'

Upon considering this further, would defining my class in /src/struct.js like this be preferable?

export default class Struct {
  static get default () {
    return Struct
  }
  ...
}

Upvotes: 1

Views: 1128

Answers (3)

Estus Flask
Estus Flask

Reputation: 222999

default exports aren't very convenient in Node.js applications because

const Struct = require('my-module').default;
const { default: Struct } = require('my-module');

requires are cumbersome and harder to read than

const Struct = require('my-module');

Due to how the interoperation with CommonJS modules works in current Babel, TypeScript (with allowSyntheticDefaultImports option) and Node native support for ES modules (.mjs modules), it's recommended to export a function like:

module.exports = Struct

so it could be imported as

import Struct from './src/struct';

in ES modules, and as

const Struct = require('./src/struct');

in CommonJS modules.

Upvotes: 1

Felix Kling
Felix Kling

Reputation: 817000

Lets look at what Babel does when you do import foo from 'bar';:

'use strict';

var _bar = require('bar');

var _bar2 = _interopRequireDefault(_bar);

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

You can see that, depending on the "type" of the imported module, Babel will either import the default export, or it will import module.exports (because require('bar') returns module.exports.

That means, in order for your module to be importable as

const Struct = require('my-module')
// and
import Struct from 'my-module'

All you have to do is

module.exports = Struct;

Upvotes: 6

yumitsu
yumitsu

Reputation: 599

Well, since nodejs still doesn't have native support for ES6 modules, for now it's really just a matter of code readability. But IMO it's no need to support both CommonJS and ES6 modules. Stick up to one.

Upvotes: 0

Related Questions