77

I tried this:

// mod.js
var a = 1;
this.b = 2;
exports.c = 3;

// test.js
var mod = require('./mod.js');
console.log(mod.a);    // undefined
console.log(mod.b);    // 2
console.log(mod.c);    // 3, so this === exports?

So I image that require() may be implement like this:

var require = function (file) {
    var exports = {};
    var run = function (file) {
        // include "file" here and run
    };
    run.apply(exports, [file]);
    return exports;
}

Is that right? Please help me to understand require(), or where can I find the source code. Thanks!

Trantor Liu
  • 8,092
  • 8
  • 41
  • 62

6 Answers6

57

Source code is here. exports/require are not keywords, but global variables. Your main script is wrapped before start in a function which has all the globals like require, process etc in its context.

Note that while module.js itself is using require(), that's a different require function, and it is defined in the file called "node.js"

Side effect of above: it's perfectly fine to have "return" statement in the middle of your module (not belonging to any function), effectively "commenting out" rest of the code

Andrey Sidorov
  • 24,056
  • 4
  • 61
  • 74
  • This doesn'y make it any simplier. That module uses `require` while it also defines `require`. That's a move I find a little bit hard to understand given that source code only. – polkovnikov.ph Sep 13 '15 at 22:44
  • require in the module itself is a different [require](https://github.com/nodejs/node/blob/v4.0.0/src/node.js#L871). Simplified version of Module is created to bootstrap module system - look at the code here - https://github.com/nodejs/node/blob/v4.0.0/src/node.js#L861-L949 – Andrey Sidorov Sep 14 '15 at 02:06
  • Where is the documentation for these global variable and its return value? – Srikan Jun 02 '17 at 00:38
  • @Srikan in official docs - https://nodejs.org/dist/latest-v8.x/docs/api/modules.html#modules_the_module_wrapper ( I'm not exactly correct about calling exports/require global variables - usually they are the arguments to a wrapper function which is called when your module is loaded ) – Andrey Sidorov Jun 02 '17 at 01:01
  • require is not a global variable tmk, it's bound to current file's __dirpath, etc. – Alexander Mills Jun 26 '18 at 06:35
  • 1
    @AlexanderMills it's not exactly global variable, it's coming from the fact that every module is wrapped inside a function and `require` is passed as one of the arguments to that function – Andrey Sidorov Jun 27 '18 at 06:49
10
var mod = require('./mod.js');

The require is a function that takes one argument called path, in this case the path is ./mod.js

when the require is invoked, a sequences of tasks are happened:

  1. call Module.prototype.require function declared in lib/module.js which assert that the path exists and was a string

  2. call Module._load which is a function in lib/module.js that resolve the file through Module._resolveFilename(request, parent, isMain),

  3. the Module._resolveFilename function is called and checks if the module is native (The native modules are returned by NativeModule function defined in lib/internal/bootstrap_node.js), if yes it will return the module else it checks the number of characters of the parh (Must 2 character at least) and some characters (the path must started by ./) via Module._resolveLookupPaths function defined in defined in lib/internal/bootstrap_node.js
  4. check the directory that contains the file
  5. If the path contains an extension (in our example yes: mod.js), the basename function defined in lib/path.js checks that the extension is "js"
  6. then it will create a new module for the file given in argument var module = new Module(filename, parent);
  7. the content will be compiled via v8 through the function NativeModule.prototype.compile defined in lib/internal/bootstrap_node.js
  8. the NativeModule.wrap defined in lib/internal/bootstrap_node.js takes the javascript content compiled of mod.js and wraps it : It wraps it in some other code that makes all this work. So the code you've written in mod.js is wrapped in a function expression. that means everything you write in node is run in V8
  9. a module.exports is what's returned
Mohamed Ben HEnda
  • 2,436
  • 1
  • 24
  • 42
7

Andrey showed the source code, but if you also wonder how to use it, the easy and simple explanation is here (http://nodejs.org/api/modules.html).

These were two good examples for me.

//foo.js, multiple methods
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

//circle.js
var PI = Math.PI;
exports.area = function (r) {
  return PI * r * r;
};
exports.circumference = function (r) {
  return 2 * PI * r;
};

//bar.js
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

//square.js, single method
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

My favourite pattern is

(function (controller) {

  controller.init = function (app) {

    app.get("/", function (req, res) {
        res.render("index", {});
    });

  };
})(module.exports);
Community
  • 1
  • 1
Andrew Chaa
  • 5,622
  • 2
  • 39
  • 31
  • If define a `var express = require('express')`, why after it, they have to redefine another variable as `var app = express()` ? – TomSawyer Aug 12 '16 at 04:32
  • didn't get how is your favourite pattern related to require – ishandutta2007 Mar 25 '17 at 19:01
  • @TomSawyer, because `require('express')` return a function that return an app. It's just the way they built it. Hopefully since you asked that question 4 years ago you already answered it. – Eric Jeker Jul 07 '20 at 05:22
1

I dig a little more of nodejs source code/2/ and make a sequence diagram/1/, hope this could give you a intuitive overview. There is another article http://fredkschott.com/post/2014/06/require-and-the-module-system/ which also explain the require() mechanism in a easy way, go through this article first could help you to understand the diagram quickly. enter image description here

Ref:

/1/ diagram source repo: https://github.com/z1yuan/nodejs.git

/2/ https://github.com/nodejs/node-v0.x-archive.git

Zhi Yuan
  • 629
  • 1
  • 11
  • 19
0

Try This.
This is a snippet of what I used to create the same functionality as Node.js

/*
FILE: require.js
*/
/*
This is the file used
*/
window.require = function(src, ret) {
  if (src === 'jsmediatags') {
    src = 'https://cdnjs.cloudflare.com/ajax/libs/jsmediatags/3.9.5/jsmediatags.js';
  };
  var d = document.createElement('script');
  d.src = src;
  document.head.appendChild(d);
  var fullURL = src.split('://');
  var neededURL = fullURL[1];
  var nameParts = neededURL.split('/');
  var nameNUM = nameParts.length - 1;
  var fileName = nameParts[nameNUM];
  var g = fileName.split('.');
  var global = g[0];
  if (ret === true) {
    return window[global]
  };
};
See if this works, and to add more files to its library, just type more in. (if (src===yourfilenamehere) { src = "path/to/your/file" }
  • 1
    This doesn't answer what the OP was asking. The OP asked how the `require` function works and how it can be implemented. This solution is how to recreate the `node.js` `require` function with pure JavaScript. – Tyler2P Dec 11 '21 at 16:46
-10

The source is available here next to the downloads : http://nodejs.org/ exports/require are keywords, I don't think they are coded in javascript directly. Node is coded in C++ , javascript is just a scripting shell around the C++ core.

Progo
  • 3,304
  • 5
  • 24
  • 43
mpm
  • 19,860
  • 7
  • 48
  • 55
  • when you just "think" or guess, it's better don't answer questions. When a module is loaded and parsed from filesystem, it's wrapped in a function and them compiled by the v8 engine, and finally the module is cached. `require`, `module`, `__filename`, etc are functions and variables injected into the module after compilation, and the module runs in the v8 engine context, but the module itself is a closure, so variables and functions are never conflicted ( except in the case you use the global variable and mess. – Jone Polvora Jul 04 '19 at 15:37