Ryan Giglio
Ryan Giglio

Reputation: 1104

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?

Upvotes: 42

Views: 29552

Answers (3)

KJ Sudarshan
KJ Sudarshan

Reputation: 3232

Just re-assign exports to module.exports

Like:

//name.js

const NameType = {
  foo: "bar",
};

function Name(name) {
  this.name = name;
}

module.exports = Name; // assign default export to Name
exports = module.exports; // re-assign exports to point it to the updated location.

exports.NameType = NameType; // now you can use named export as usual

In another file you can import like:

const Name = require("./name");
const { NameType } = require("./name");

This works because by default module = { exports: {} } and exports = module.exports

Reference: Difference between "module.exports" and "exports" in the CommonJs Module System

Upvotes: 8

Shannon Hochkins
Shannon Hochkins

Reputation: 12175

If you don't want to repeat the named exports, you can always do something like

module.exports = defaultFunction;
module.exports = Object.assign(module.exports, {
    namedFunction1,
    namedFunction2,
});

Then you can require as normal;

const myModule = require('./myModule');
myModule();
myModule.namedFunction1();

Upvotes: 1

Trott
Trott

Reputation: 70075

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!'

Upvotes: 79

Related Questions