Search code examples
node.jsimportecmascript-6exportcommonjs

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
  }
  ...
}

Solution

  • 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;