Understanding module.exports and exports in Node.js

By Cho S. Kim

As developers, we often face situations where we need to use unfamiliar code. A question will arise during these moments. How much time should I invest in understanding the code that I’m about to use? A typical answer is learn enough to start coding; then explore that topic further when time permits. Well, the time has come to gain a better understanding of module.exports and exports in Node.js. Here’s what I have learned.

Note: This post covers using modules in Node. If you want to learn how you can use modules inside of the browser, read: Understanding JavaScript Modules: Bundling & Transpiling

What is a Module

A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file. Let’s illustrate this point with an example involving an application built with Node.js. Imagine that we created a file called greetings.js and it contains the following two functions:

// greetings.js
sayHelloInEnglish = function() {
  return "Hello";

sayHelloInSpanish = function() {
  return "Hola";

Exporting a Module

The utility of greetings.js increases when its encapsulated code can be utilized in other files. So let’s refactor greetings.js to achieve this goal. To comprehend what is actually happening, we can follow a three-step process:

1) Imagine that this line of code exists as the first line of code in greetings.js:

// greetings.js
var exports = module.exports = {};

2) Assign any expression in greetings.js that we want to become available in other files to the exports object:

// greetings.js
// var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
  return "HELLO";
exports.sayHelloInSpanish = function() {
  return "Hola";

In the code above, we could have replaced exports with module.exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.

3) This is the current value of module.exports:

module.exports = {
  sayHelloInEnglish: function() {
    return "HELLO";
  sayHelloInSpanish: function() {
    return "Hola";

Importing a Module

Let’s import the publicly available methods of greetings.js to a new file called main.js. This process can be described in three steps:

1) The keyword require is used in Node.js to import modules. Imagine that this is how require is defined:

var require = function(path) {

  // ...

  return module.exports;

2) Let’s require greetings.js in main.js:

// main.js
var greetings = require("./greetings.js");

The above code is equivalent to this:

// main.js
var greetings = {
  sayHelloInEnglish: function() {
    return "HELLO";
  sayHelloInSpanish: function() {
    return "Hola";

3) We can now access the publicly available methods of greetings.js as a property of our greetings variable in main.js.

// main.js
var greetings = require("./greetings.js");

// "Hello"
// "Hola"  

Salient Points

The keyword require returns an object, which references the value of module.exports for a given file. If a developer unintentionally or intentionally re-assigns module.exports to a different object or different data structure, then any properties added to the original module.exports object will be unaccessible.

An example will help elaborate this point:

// greetings.js
// var exports = module.exports = {};

exports.sayHelloInEnglish = function() {
  return "HELLO";

exports.sayHelloInSpanish = function() {
  return "Hola";

 * this line of code re-assigns  
 * module.exports
module.exports = "Bonjour";

Now let’s require greetings.js in main.js:

// main.js
var greetings = require("./greetings.js");

At this moment, nothing is different than before. We assign the variable greetings to any code that is publicly available in greetings.js.

The consequence of re-assigning module.exports to a data structure other than its default value is revealed when we attempt to invoke sayHelloInEnglish and sayHelloInSpanish:

// main.js
// var greetings = require("./greetings.js");
 * TypeError: object Bonjour has no 
 * method 'sayHelloInEnglish'
 * TypeError: object Bonjour has no 
 * method 'sayHelloInSpanish'

To understand why these errors are occuring, let’s log the value of greetings to a console:

// "Bonjour"

At this point, we are trying to access the methods sayHelloInEnglish and sayHelloInSpanish on the string “Bonjour.” module.exports, in other words, is no longer referencing the default object that contain those methods.


Importing and exporting modules is a ubiqutous task in Node.js. I hope that the difference between exports and module.exports is clearer. Moreover, if you ever encounter an error in accessing publicly available methods in the future, then I hope that you have a better understanding of why those errors may occur.

  • jokeyrhyme

    I’ve found it less confusing to just avoid the `exports` variable altogether.

    • Cho S. Kim

      That makes a lot of sense.

    • Bushwazi

      Can you explain this more? I tried changing `exports.sayHelloInSpanish = function(){return “Hola”;}` to `sayHelloInSpanish = function(){return “Hola”;}` and I got an error. And `console.log(greetings);` just returned and empty object {}. Do you have to structure greetings.js different to make it work this way?

      • jokeyrhyme

        This article looks at exports and module.exports.

        Given the choice, I avoid exports, and only use module.exports.

      • Cho S. Kim

        I believe that jokeyrhyme’s initial comment could have been misinterpreted for avoiding the use of both exports and module.exports. He clarified what he meant in his reply to your question (using module.exports instead of exports), but I’ll try to answer your question, too.

        Question 2 of 2: console.log(greetings);
        Imagine this is the file we are talking about and the comments represent code that’s implied:

        // var module.exports = {};

        sayHelloInSpanish = function() {
        return “Hola”;

        // module.exports = {};

        When you require this file in a different file, you’re returning module.exports. In this case, you never added a method called sayHelloInSpanish to module.exports. So this explains why an empty object is being returned in the console.

        Question 1 of 2: you received an error
        This may be in reference to a syntactical error. I can confirm this if you provide more information, such as the code in the file you are using. Or you can tell me the type of error; however, seeing the file is probably the easiest approach.

        I hope this helps.

        • Bushwazi

          Sorry, it’s obvious now that I look again. jokeyrhyme’s just saying he prefers this pattern (is this a constructor/ object initializer?):

          module.exports = {

          methodName: function(){}


          and you were showing a different pattern (and this is “Dot syntax”?):

          exports.mathodName = function(){};

          to accomplish the same thing.

          Let me know if I still don’t get it…

          • Cho S. Kim

            Yes, he was using an object literal to add methods and I was using dot notation to add methods. Both syntax works, but I choose the later because adding a lot of methods to an object literal delays the end of the object literal (closing curly brace) for many lines of code.

            I hope this helps.

          • Bushwazi

            Yeah man, this was great. Thank You!

          • Manuel Conde Vendrell

            This is the explanation I was waiting for. The reason to choose one or the other way to export the functions. I was using the same than you ( = function) but just for a reason of that I have some functions that I don’t want to export (are helpers) and other than yes. Now I know that it has a little performance reason too.

  • Dave McFarland

    I’m sorry I don’t get it. What IS the difference between exports and module.exports? It sounds like they are the same thing: “In the code above, we could have replaced exports with module.exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.”

  • ConnieRWright

    Start working at home with>>CLICK NEXT TAB FOR MORE INFO AND HELP

  • Cho S. Kim


    Thanks for leaving a comment. Both module.exports and exports initially reference the same object:

    var exports = module.exports = {};

    But this could change if a developer re-assigns module.exports or exports to a different object (or entirely different data type). This usually occurs when developers use exports and module.exports interchangeably and incorrectly to make assignments in the same file.

    Here’s the difference between exports and module.exports: When a module is being required in a file, what’s being returned from the require function is the value of module.exports. So this is worth repeating, the difference is that the require function returns only the value of module.exports, which initially references an object.

  • rosy lily

    I get paid over $87 per hour working from home with 3 kids at home. I never thought I’d be able to do it but my best friend earns over 10k a month doing this and she convinced me to try. The potential with this is endless.

    Here ­­­­­­­­­is ­­­­­­­­­I ­­­­­started>>>>>>>>>➜➜➜➜➜➜➜

    ➜➜➜➜ W­W­W­.­N­E­T­P­A­Y­1­0­.ℭ­ℴ­m



  • Quynh Le

    Thank you very much. It is clear now for me.

  • nor

    The principal difference is what module.exports replace the content of the exports only if exports previously has an value and this is only valid if you have the declaration exports first and then you write module.export. In summary use one of it not both.

  • Alex

    Thank so much for this very clear presentation. Very helpful to me.

  • Mustafa Gamal

    Thanks for the simplicity :)

    • Cho S. Kim


  • Vengatesh TR

    wow. beautiful & detailed explanation. Thanks :)

    • Cho S. Kim

      Thanks for the positive feedback.

  • Cho S. Kim

    You’re welcome :).

  • Cho S. Kim

    I’m happy that it was useful.

  • Jahanzaib Aslam

    Simple and to the point. Thanks

  • Darnell Filliams

    Thank you very much. This was very clear and well-written.

  • ConfusedCoder

    Thank you! Simple and clear, great tutorial!

  • joe

    var module.exports = { } is a syntax error. You can’t use member variables in var declaration.

    • Cho S. Kim

      Hey, Joe. I believe that you’ve misread the syntax:
      var exports = module.exports = {};
      Considering the syntax above, the pointers move from right to left. So it’s more like this:
      module.exports = {};
      var exports = modules.exports

  • Luke Swart

    Thanks for the post! We need more elegant explanations for ubiquitous topics such as module exports.

  • Sergey Gulidov

    Thanks, it was useful for me)

  • Andrew Hung

    Great explanation, Cho. Thanks for writing this. Definitely cleared things up for me.

  • مهدی پیشگوی

    Thanks, it was useful tutorial

  • Clint Goodman

    Hey this was excellent. Thank you very much. I loved the way that you helped me visualize what was going on. I want to read more of your stuff.

    • Cho S. Kim

      Thanks for the positive feedback. I’ll let you know when I publish more content.

  • David Christiandy

    It is actually the same thing. Here’s a simple way to put it: imagine that `module` is just plain Javascript object:

    var module = {}
    var exports = module.exports = {}

    module.exports.hello = “Bonjour”
    console.log(module.exports) // Object {hello: “Hello”}
    console.log(exports) // Object {hello: “Hello”}

    exports = null;
    console.log(module.exports) // Object {hello: “Hello”}
    console.log(exports) // null

    • Chi

      Hmmm… so according to your example, exports initially points to module.exports by default. You invalidate the pointer by pointing “exports” to null or any other object for that matter. I finally get how this process works. Thanks!

  • leon

    Ranks high in google search.
    It is very helpful for understanding commonJS.
    Thanks for sharing this!

  • Dan Chan

    I followed your example. But, it did not work. I got this error:

    “Uncaught Error: Module name “/greetings.js” has not been loaded yet for context: _. Use require([])

    Any idea? What did I do wrong?


    • Cho S. Kim

      Sorry for not responding sooner. @nazmulhoqueshafin:disqus, noticed the error. You’re loading your own module and you didn’t specify the path correctly to it.

  • Ademola Adedeji

    Thank you

  • Aurelius

    Thanks this was helpful

  • lacyrhoades

    Thank you!

  • Frank Wang

    very helpful!

  • Nazmul Hoque Shafin

    just put a period (.) before the “/.greetings.js” . I mean you should write require(“./greetings.js”); instead of equire(“/greetings.js”);

  • D. Attila

    Easy to follow and crystal clear, many thanks!

  • Tyler Maynard

    Slight error in the document. It appears the expression for your Author isn’t evaluating because the closing brace is a bracket (or vice versa):


    Other than that great points. I personally prefer to section out my module with many exports statements then returning one large object, but both have their purpose. If I create a large class than module.exports comes in handy, but if I am creating a handful of utility functions, then exports(dot) is my best friend.

    • Cho S. Kim

      Thanks for bringing the error about the closing to my attention. I’ll forward this info to the editor.

      In regards to other comments, they seem very logical.

  • GJ

    Thank you much. Very helpful.

  • Jordan Neufeld

    Thank you for this post!

  • Joseph Diku

    Thank You for the write up, it’s clearer to me now

  • Mahmod Issa

    Thanks a lot, clarified some points that I was in doubt!

  • Pride007

    Really good explanation, finally it’s all clear. thanks Kim

  • Paulo Matos

    It was really useful. Thank you!

  • Christian Cros

    Hello Cho, thank you very much for this article, it is very helpful! :)

  • Goon

    Simple. Clear. Awesome.

  • roflmyeggo

    Good tips Cho! Exactly what I was looking for. Thanks.

  • Vitez Koja

    Ty you Sir :)

  • Francis Kwan

    thank you . this is very clear explanation. :)

  • Ronak Amlani

    Thank you thank you so much..

  • UATP

    Isn’t the reason that module.exports and exports refer to the same object simply because of the line:

    var exports = module.exports = {};
    What is odd is that it exists in 1.) but it’s commented out in 2.), so either it’s commented because it’s meant to be a comment about what is happening behind the scenes or because it’s a typo in the example.

    Still a little confused.

    • Cho S. Kim

      @uatp:disqus : Sorry for the delay. It’s the former–a comment about what’s happening.

  • Welquer Kestering Esser

    Thank you, it helped me a lot!

  • Rulo Kobashikawa

    Hi, thank you for the tutorial.
    Currently, with node 5.5.0 I found:

    exports = ‘Hello’; // {}

    exports.hello = ‘Hello’; // {hello: ‘Hello’}

    module.exports = ‘Hello’; // {hello: ‘Hello’}

    module.exports.hello = ‘Hello’; // {hello: ‘Hello’}

    so, it seems exports and module.exports are not the same

  • Eduardo Irías

    Interesting article thanks!

  • Brendan Moran

    Great explanation! So clear, I feel like I’ve really got a handle on it now. Thank you.

  • milind

    Thanks Cho S. Kim,Realy very useful tutorial.

  • Nick Restrepo

    “Here’s his blog” – BAM Chinese words everywhere. Really cool font though.

    • Cho S. Kim

      @nick_restrepo:disqus, ehk. I let my domain name expire, and someone decided to take it…even though they have no connection with my name.

      I recently bought a new domain name, and I’ll give SitePoint the updated link, soon.



Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.