Node.js全局require

10

如何全局引用一个模块,以便在不同的模块中使用而无需再次引用它?还是每次都需要引用它? 有没有最佳实践来解决这个问题?

下面是我所说的一个示例。假设我有一个名为index.js的文件,内容如下:

var a = require('a.js'),
utils = require('utils.js');

var str = 'hello this is a test';
str = a.change(str);

utils.return(str);

a.js

var utils = require('utils.js');

exports.change = function(str) {
    str = str.replace('test', 'example');
    utils.return('i changed test to example!');
    return str;
}

utils.js

exports.return = function (msg) {
    console.log(msg);
}

我需要在两个地方都引入'utils.js',但我宁愿只在index.js中引入一次,并在index.js和a.js中都能使用utils。有没有好的方法实现这一点?


2
我也遇到了类似的问题(stackoverflow.com/questions/31196572/parse-is-undefined-in-node-js-controller),期待看到你问题的答案。这可能也能解决我的问题。 - Amir
2个回答

16
在nodejs开发中,通常的做法是在需要使用某个模块的每个模块中使用require()来引入它。该模块本身由nodejs缓存,因此每次返回相同的模块实例,并且不会重复加载。这种方式与创建全局变量相比通常使代码更具模块化和可重用性,因为每个模块都使用require()语句唯一地指定了其需要的内容,而不是依赖于一些预先存在的全局配置,从而创建了更多的依赖项、加载顺序问题等等...。
如果有必要,可以创建一个单独的模块,在其中对其他模块进行require(),然后将结果组合成一个新的主模块,以便其他模块只需引入新的主模块即可。
不建议使用全局变量来替代require()语句。请记住,在nodejs编程中,大多数require()语句仅在服务器初始化时运行,并且它们被缓存,因此没有理由避免使用require()而放弃其提供的好处和模块化特性,而采用全局变量。
我个人不建议这样做,因为它会干扰模块化,但在您的特定示例中,您也可以将utils模块传递给a.js构造函数。
var utils = require('utils.js');
var a = require('a.js')(utils);

感谢您的回答。问题是,我有一个高度模块化的项目,许多模块需要在其他模块内部使用。这导致每个模块开头都有一个巨大的 require 语句块,我认为这非常丑陋。我知道所需的模块已被缓存,这并不是我的问题。我只想摆脱每个模块中的巨大 require 块。 - John Jackson
@JohnJackson - 所以,你已经将模块化做到了极致,现在想要通过一堆全局变量来取消模块化?你能看到这里的讽刺吗?如果你想要使用全局变量并且以某种方式仔细控制加载顺序,那么你当然可以自由地使用它们 - 我只是不知道有谁认为这是一个好的设计模式。而且,这会破坏模块化的许多优点,因为使用全局变量的模块将不再是自包含的,也无法单独使用(除非某个主机首先创建正确的全局变量)。 - jfriend00
@JohnJackson - 提醒一下,易于维护、可重用和模块化的设计是有成本的。在这种情况下,听起来你已经将事物设计成了小模块。实际上使用它的方法就是在每个模块中简单地插入必要的require()语句。如果你真的不喜欢这样做,那么你只是放弃了你的模块化设计大部分优势(除了拥有许多小文件)。模块化最大的优势是易于重用,如果你依赖一堆全局变量,你就无法做到这一点。 - jfriend00

0

对于将来在谷歌搜索此问题的人,您可以使用global变量。只有在非常特定的场合下才能这样做(例如:代码在每个文件中复制)

global.mymodule = require("mymodule");
mymodule.abc // works in any file in the same process

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接