mister blinky
mister blinky

Reputation: 554

Javascript CommonJS - where's the module?

So I'm using modules in a personal project for the usual reasons (namespace protection and dependency handling (require) and public API definition (exports)). I wrote my own require() method and am using the standard module pattern -- i.e.:

var myModule = (function() {
   var exports = {};

   function sayHello() {
      return "hi";
   }
   exports.sayHello = sayHello;

   return exports;
})();

So I want to standardize my stuff on CommonJS standard (this is for server-side JS and my question is not about CommonJS versus other module standards). Everything I read about CommonJS says that a module looks like this

function sayHello() {
   return "hi";
}
exports.sayHello = sayHello

And that's it! But that's not a module. Something must be wrapping this as an actual module! I have not found a single site discussing CommonJS modules that says how this gets turned into an actual module. Am I missing something that everybody else seems to know?

So my questions are:

What is doing the wrapping? -- i.e., what turns it into an actual module? A library of some sort, I assume.

What does this final, wrapped, CommonJS module look like? I want to write an implementation of the CommonJS standard, but can't find any documentation of what that final module is supposed to look like.

Is the "exports" variable in the global scope? If not, what is providing the exports object to the module if it's not being explicitly declared in the body of the module code? And who's doing it - the caller of the module?

Dang. It seemed simple when I wrote it myself. Now it seems like magic. A link to some comprehensive documentation would be great.

NOTE: I know very little about node.js and don't intend to use it in this project, so if you answer, please don't answer in node.js-speak.

Upvotes: 3

Views: 1384

Answers (2)

Roman Mahotskyi
Roman Mahotskyi

Reputation: 6655

I hope that node.js documentation can answer all of your questions.

So, according to the node.js documentation

Before a module's code is executed, Node.js will wrap it with a function wrapper that looks like the following:

(function(exports, require, module, __filename, __dirname) {
  // Module code actually lives in here
});

By doing this, Node.js achieves a few things:

  • It keeps top-level variables (defined with var, const or let) scoped to the module rather than the global object.
  • It helps to provide some global-looking variables that are actually specific to the module, such as:
    • The module and exports objects that the implementor can use to export values from the module.
    • The convenience variables __filename and __dirname, containing the module's absolute filename and directory path.

Upvotes: 0

shennan
shennan

Reputation: 11676

What is doing the wrapping?

Node is. It can access the filesystem, so it caches the code from all the files that have been required, and delivers it to the namespaces that required it.

What does this final, wrapped, CommonJS module look like?

The actual code where modules are wrapped will probably be in module.js, which is a core file in the lib folder of Node's installation.

Is the "exports" variable in the global scope?

The exports is a property of the module object within a file. The module is the global scope inside that file. The exports property is what is returned by the module to the code that requires it.

The key thing to remember is that the CommonJS ethos is built-in to Node's core modular code. There is no magical implementation in the V8 which dictates that module.exports is a 'thing'. This may all change when implementing ES6 modules becomes the norm.

You might find it useful reading this.

You may find it even more useful to give up on your quest to re-write require(). :-)

Upvotes: 2

Related Questions