How does require() in node.js work?
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.
Ref:
/1/ diagram source repo: https://github.com/z1yuan/nodejs.git
/2/ https://github.com/nodejs/node-v0.x-archive.git
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);
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
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:
call
Module.prototype.require
function declared in lib/module.js which assert that the path exists and was a stringcall
Module._load
which is a function in lib/module.js that resolve the file throughModule._resolveFilename(request, parent, isMain)
,- the
Module._resolveFilename
function is called and checks if the module is native (The native modules are returned byNativeModule
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./
) viaModule._resolveLookupPaths
function defined in defined in lib/internal/bootstrap_node.js - check the directory that contains the file
- 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"
- then it will create a new module for the file given in argument
var module = new Module(filename, parent);
- the content will be compiled via v8 through the function
NativeModule.prototype.compile
defined in lib/internal/bootstrap_node.js - the
NativeModule.wrap
defined in lib/internal/bootstrap_node.js takes the javascript content compiled ofmod.js
and wraps it : It wraps it in some other code that makes all this work. So the code you've written inmod.js
is wrapped in a function expression. that means everything you write in node is run in V8 - a module.exports is what's returned