How module.exports and exports work in Node.js

How module.exports and exports work in Node.js

I’m going to talk about how to work with modules in Node.js, specifically how to export and import them.

Main Points

  • Modules make developing with Node.js better: Node.js modules are essential for making code that works well, is easy to update, and can be used again and again.
  • How to Understand the Different Node.js Module Formats: The article talks about a number of different module formats in Node.js, such as CommonJS, AMD, ESM, System.register, and UMD. Each of these forms is useful for different things. But it mostly works on the CommonJS format, which is standard in Node.js and uses require and module.exports to set up modules and dependencies.
  • Exporting and Using Modules: This article tells you everything you need to know to make, export, and use modules in Node.js. It talks about the different ways to use syntax when exporting multiple values and methods, how to use module.exports for default exports, and the small changes between exports and module.exports.

Different Types of Node.js Modules

Since modules weren’t part of JavaScript at first, many alternative formats have grown over time. Here is a list of the most important ones:

  • Browsers use the Asynchronous Module Definition (AMD) format, which has a define method that is used to set up modules.
  • In Node.js, the standard is CommonJS (CJS), and require and module.exports are used to set up modules and dependencies. It’s what the npm community is built on.
  • The standard for the ES Module (ESM). JavaScript now has a native module style as of ES6 (ES2015). An export keyword is used to send the public API of a module out, and an import keyword is used to bring it back in.
  • The System.register style was made so that ES6 modules could be used in ES5.
  • It is possible to use the Universal Module Definition (UMD) standard in both browsers and Node.js. It’s helpful when more than one module loader needs to bring in the same module.

Please keep in mind that this piece only talks about the CommonJS format, which is the standard in Node.js.

Requiring a Module

There are some tools that come with Node.js that we can use in our code without having to install them. In order to do this, we need to use the require keyword to call the module and then give the result to a variable. After that, this can be used to call any methods that the module provides.

As an example, you can use the file system module and its readdir method to see what’s in a directory:

const fs = require('fs');
const folderPath = '/home/jim/Desktop/';

fs.readdir(folderPath, (err, files) => {
  files.forEach(file => {
    console.log(file);
  });
});

Keep in mind that in CommonJS, modules are loaded at the same time and are handled in the order they appear.

Making a Module and Exporting It

Let’s look at how to make our own module and then use it in another part of our programme by exporting it. First, make a file called user.js and add the following:

const getName = () => {
  return 'Jim';
};

exports.getName = getName;

Now make a file called index.js in the same folder and add this:

const user = require('./user');
console.log(`User: ${user.getName()}`);

When you run the programme with node index.js, the screen should show the following:

User: Jim

What the heck is going on? You can see that we defined a getName method in the user.js file and then used the exports keyword to make it available for use in other files. Then we’ll import this method and run it in the index.js file. Also, keep in mind that the module name starts with./ in the require line because it is a local file. Don’t forget to add the file name either.

Exporting More Than One Values and Methods

In the same way, we can send more than one method and value:

const getName = () => {
  return 'Jim';
};

const getLocation = () => {
  return 'Munich';
};

const dateOfBirth = '12.01.1982';

exports.getName = getName;
exports.getLocation = getLocation;
exports.dob = dateOfBirth;

It also has index.js:

const user = require('./user');
console.log(
  `${user.getName()} lives in ${user.getLocation()} and was born on ${user.dob}.`
);

This is what the above code does:

Jim lives in Munich and was born on 12.01.1982.

We can give the exported dateOfBirth variable any name we want, like “dob” in this case. The new name doesn’t have to be the same as the old one.

Changes to the syntax

Also, you don’t have to export methods and values at the end of the file; you can do it all the way through.

As an example:

exports.getName = () => {
  return 'Jim';
};

exports.getLocation = () => {
  return 'Munich';
};

exports.dob = '12.01.1982';+

We can pick and choose what to import thanks to destructuring assignment:

const { getName, dob } = require('./user');
console.log(
  `${getName()} was born on ${dob}.`
);

As you might guess, this logs:

Jim was born on 12.01.1982.

Putting a default value out there

In the above case, we are exporting both functions and values separately. With this, you can easily add helper functions that could be used across an app. However, module is more popular when you only want to export one thing.Leaving the country

class User {
  constructor(name, age, email) {
    this.name = name;
    this.age = age;
    this.email = email;
  }

  getUserStats() {
    return `
      Name: ${this.name}
      Age: ${this.age}
      Email: ${this.email}
    `;
  }
}

module.exports = User;

It also has index.js:

const User = require('./user');
const jim = new User('Jim', 37, 'jim@example.com');

console.log(jim.getUserStats());

This is recorded by the code above:

Name: Jim
Age: 37
Email: jim@example.com

Why are module.exports and exports not the same thing?

You may come across the following code as you browse the Internet:

module.exports = {
  getName: () => {
    return 'Jim';
  },

  getLocation: () => {
    return 'Munich';
  },

  dob: '12.01.1982',
};

Here, we’re telling the module’s exports property about the functions and values we want to send out. This works perfectly, of course:

const { getName, dob } = require('./user');
console.log(
  `${getName()} was born on ${dob}.`
);

This keeps track of the following:

Jim was born on 12.01.1982.

Kind of, but not quite…

Let’s change the code in index.js to log the value of module to show what I mean:

Module {
  id: '.',
  exports: {},
  parent: null,
  filename: '/home/jim/Desktop/index.js',
  loaded: false,
  children: [],
  paths:
   [ '/home/jim/Desktop/node_modules',
     '/home/jim/node_modules',
     '/home/node_modules',
     '/node_modules' ] }

This leads to:

// index.js
exports.foo = 'foo';
console.log(module);

One of the things that module does is exports. Let’s add something:

This leads to:

Module {
  id: '.',
  exports: { foo: 'foo' },
  ...

When you give traits to exports, they are also added to module.exports. This is because exports is a reference to module.exports (at least at first).

Which one should I use then?

As long as both exports and module.exports point to the same object, it doesn’t matter which you use. As an example:

foo: ‘foo’, bar: ‘bar’ would be the module’s shared object if this code was used.

But there is one catch. Whatever you give module.exports is what your module sends out.

So, here’s what to do:

This would only lead to the export of an unnamed function. The variable foo would not be used.

I think this piece will help you learn more about the difference.

Conclusion

Modules are now an important part of JavaScript because they let us put together big programmes from smaller ones. I hope this piece has helped you understand their syntax and given you a good start on working with them in Node.js.

If you want to start a conversation about something, you can go to the SitePoint boards and post it.

How to Use module.exports and exports in Node

In Node.js, what’s the difference between exports and module.exports?

When you want to export data from a module, you can use either module.exports or exports. You can use either exports or module.exports since they are basically the same thing. It is generally better to use module.exports, though, to avoid problems.

In the same module file, can I use both module.exports and exports?

Yes, you can use both of them in the same part. Just be careful, because it could cause them to act in strange ways. To be consistent, it’s best to stick to one rule.

What are some mistakes people often make when they use module.exports and exports?

Reassigning exports straight is a common mistake that can have bad outcomes. A better way to keep things consistent and avoid problems is to use module.exports.

Is there a change in how well module.exports and exports work?

In terms of performance, there aren’t any big changes between the two. They are mostly different in terms of how they are coded and how they are used.

Can I use exports and module.exports in the browser, or are they only for Node.js?

You can’t use module.exports and exports in browser JavaScript; they are only available in Node.js. Exporting and importing are usually done in other ways in the browser, such as with ES6 modules.