78

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,770
  • 8
  • 44
  • 64

7 Answers7

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,905
  • 4
  • 62
  • 75
  • 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
11
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,686
  • 1
  • 30
  • 44
9

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
  • 6,120
  • 2
  • 45
  • 33
  • 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
2

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
  • 779
  • 1
  • 13
  • 20
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
0

The module loading mechanism in Node.js is caching the modules on the first require call. It means that every time you use require('xyz-module') you will get the same instance of xyz-module, which ensures that the modules are singleton-like and have the same state across your application.

You can load native modules and path references from your file system or installed modules. If the identifier passed to the require function is not a native module or a file reference (beginning with /, ../, ./ or similar), then Node.js will look for installed modules. It will walk your file system looking for the referenced module in the node_modules folder. It starts from the parent directory of your current module and then moves to the parent directory until it finds the right module or until the root of the file system is reached.

Md. Al Amin Bhuiyan
  • 303
  • 1
  • 3
  • 12
-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,452
  • 5
  • 27
  • 44
mpm
  • 20,148
  • 7
  • 50
  • 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