简体   繁体   English

node.js 中的 require() 是如何工作的?

[英]How does require() in node.js work?

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:所以我认为 require() 可能是这样实现的:

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.请帮助我理解 require(),或者我在哪里可以找到源代码。 Thanks!谢谢!

Source code is here . 源代码在这里 exports / require are not keywords, but global variables. exports / require不是关键字,而是全局变量。 Your main script is wrapped before start in a function which has all the globals like require , process etc in its context. 您的主脚本在开始之前 包装在一个函数中,该函数在其上下文中具有所有的全局变量,例如requireprocess等。

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" 请注意,虽然module.js本身正在使用require() ,但这是一个不同的require函数,它在名为“ 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 上面的副作用:在模块的中间(不属于任何函数)使用“ return”语句,可以有效地“注释”其余代码,这是完全可以的

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 ). Andrey显示了源代码,但是如果您还想知道如何使用它,则在此处( 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);
var mod = require('./mod.js');

The require is a function that takes one argument called path, in this case the path is ./mod.js require是一个带有一个称为path的参数的函数,在这种情况下,路径为./mod.js

when the require is invoked, a sequences of tasks are happened: 调用require时,将发生一系列任务:

  1. call Module.prototype.require function declared in lib/module.js which assert that the path exists and was a string 调用lib / module.js中声明的Module.prototype.require函数,该函数断言路径存在并且是字符串

  2. call Module._load which is a function in lib/module.js that resolve the file through Module._resolveFilename(request, parent, isMain) , 调用Module._load这是lib / module.js中的一个函数),该函数通过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 调用Module._resolveFilename函数并检查该模块是否为本地模块(本地模块由lib / internal / bootstrap_node.js中定义的NativeModule函数返回),如果是,它将返回该模块,否则检查模块的字符数通过lib / internal / bootstrap_node.js中定义的Module._resolveLookupPaths函数来解析parh(至少2个字符)和一些字符(路径必须以./ Module._resolveLookupPaths )。
  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 " 如果路径包含扩展名(在我们的示例中为:mod.js),则lib / path.js中定义的basename函数将检查扩展名是否为“ js
  6. then it will create a new module for the file given in argument var module = new Module(filename, parent); 然后它将为参数var module = new Module(filename, parent);给定的文件创建一个新模块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 内容将通过v8通过lib / internal / bootstrap_node.js中定义的NativeModule.prototype.compile函数进行编译
  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. NativeModule.wrap中定义的lib /内部/ bootstrap_node.js需要编译的JavaScript内容mod.js并把它封装:它把它封装在其他一些代码,使所有这些工作。 So the code you've written in mod.js is wrapped in a function expression. 因此,您在mod.js编写的代码将包装在函数表达式中。 that means everything you write in node is run in V8 这意味着您在节点中编写的所有内容均在V8中运行
  9. a module.exports is what's returned 返回的是module.exports

I dig a little more of nodejs source code/2/ and make a sequence diagram/1/, hope this could give you a intuitive overview. 我进一步研究了nodejs源代码/ 2 /,并制作了一个序列图1/1 /,希望这可以给您直观的概述。 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. 还有另一篇文章http://fredkschott.com/post/2014/06/require-and-the-module-system/ ,它也以一种简单的方式解释了require()机制,请先阅读本文可以帮助您快速了解该图。 在此处输入图片说明

Ref: 参考:

/1/ diagram source repo: https://github.com/z1yuan/nodejs.git / 1 /图表源仓库: https : //github.com/z1yuan/nodejs.git

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

Try This.试试这个。
This is a snippet of what I used to create the same functionality as Node.js这是我用来创建与 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" } 看看这是否有效,并向其库添加更多文件,只需输入更多。 (if (src===yourfilenamehere) { src = "path/to/your/file" }

The module loading mechanism in Node.js is caching the modules on the first require call. Node.js 中的模块加载机制是在第一次require调用时缓存模块。 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.这意味着每次使用require('xyz-module')时,您都会获得相同的xyz-module实例,这确保了模块是单例的,并且在您的应用程序中具有相同的 state。

You can load native modules and path references from your file system or installed modules.您可以从文件系统或已安装的模块加载native 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.如果传递给require function 的标识符不是本机模块或文件引用(以 /、../、./ /, ../, ./ or similar开头),则 Node.js 将查找已安装的模块。 It will walk your file system looking for the referenced module in the node_modules folder.它将遍历您的文件系统,在 node_modules 文件夹中查找引用的模块。 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.它从当前模块的父目录开始,然后移动到父目录,直到找到正确的模块或到达文件系统的根目录。

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. 该资源可在下载旁边找到: http : //nodejs.org/exports/require是关键字,我认为它们不是直接用javascript编码的。 Node is coded in C++ , javascript is just a scripting shell around the C++ core. Node用C ++编码,而javascript只是C ++核心周围的脚本外壳。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM