Search code examples
javascriptnode.jsnode-modulesecmascript-5

Mixed default and named exports in Node with ES5 syntax


All my experience with exporting/importing modules has come in ES6 using export and import, where you can do something like this to have a single module export a default function as well as separate named functions.

// module.js
export default mainFunction
export { namedFunction }

// main.js
import mainFunction from 'functions'
mainFunction()

import { namedFunction } from 'function'
namedFunction()

However I can't figure out how to do this with ES5 style imports using module.exports and require. As far as I understand, I can export either a single default:

// module.js
module.exports = function mainFunction() {}

// main.js
const mainFunction = require('module.js')

Or I can create named exports:

// module.js
module.exports = {
  namedFunction: function() {}
}

// main.js
const namedFunction = require('module.js').namedFunction

But I can't do both. I thought I could maybe name one of the exports "default" like this, but it doesn't work

// module.js
module.exports = {
  default: function() {},
  namedFunction: function() {}
}

// main.js
const mainFunction = require('module.js') // does not work
const mainFunction = require('module.js').default // works, but not what I want
const namedFunction = require('module.js').namedFunction

How can I accomplish this dual default/named export with ES5?


Solution

  • You want to assign the value of module.exports to be your default function, and then put all the named exports as properties on that function.

    const defaultFunction = () => { console.log('default!'); };
    const namedFunction1 = () => { console.log('1!'); };
    const namedFunction2 = () => { console.log('2!'); };
    
    const myModule = module.exports = defaultFunction;
    myModule.namedFunction1 = namedFunction1;
    myModule.namedFunction2 = namedFunction2;
    

    Let's say that was in myModule.js. Then you can do this:

    const myModule = require('./myModule');
    myModule(); // Prints: 'default!'
    myModule.namedFunction1(); // Prints: '1!'