如何使用Node.js在服务器端管理多个JS文件

55

我正在使用Node.js开发一个项目,由于服务器端的代码越来越多,因此我希望将其拆分成多个文件。在客户端方面,这似乎已经做了很长时间,通过为每个文件插入script标签进行开发,而只有在分发时才使用类似“ Make”之类的东西将所有内容组合在一起。我意识到没有必要将所有服务器端代码连接在一起,因此我不会询问如何执行此操作。我能找到的最接近的方法是require(),但它的行为与浏览器中的script不完全相同,因为require的文件不共享通用命名空间。

查看一些旧的Node.js项目,比如Shooter,似乎曾经不是这种情况,否则我可能在我的代码中遗漏了一些简单的东西。在编译时或运行时,我的require'd文件无法访问全局调用命名空间。是否有任何简单的方法解决这个问题,或者我们被迫使我们的require'd JS文件完全独立于调用范围?

2个回答

70

你不希望使用共享命名空间,因为全局变量是有害的。在 Node 中,我们定义模块。

// someThings.js

(function() {
    var someThings = ...;

    ...

    module.exports.getSomeThings = function() {
        return someThings();
    }

}());

// main.js

var things = require("someThings");
...
doSomething(things.getSomeThings());

你需要定义一个模块,然后通过编写到exports的内容来公开模块的公共API。

最好的处理方式是依赖注入。你的模块公开了一个init函数,并将依赖项对象哈希传递给你的模块。

如果你真的坚持要访问全局范围,那么可以通过global访问它。每个文件都可以向global对象写入和读取。但是你不想使用全局变量。


感谢提供的信息,我会将其标记为正确。我基本上同意全局变量等于邪恶的概念,但它们似乎确实有其存在的地方。例如,如果我有一个基本属性,我想为给定的“类”设置该属性,该属性取决于其他地方的值怎么办?例如: SomeClass.prototype.baseProp = SomeOtherClass.prototype.prop * 2; 在这种情况下,我要么被迫通过构造函数在对象实例化时设置它,要么使用您建议的global对象。我认为后者可能是最合适的。 - Matt Molnar
3
@XHR 然后SomeClass依赖于SomeOtherClass,你需要在SomeClass.js中使用require("SomeOtherClass")。在我的代码中我有一个全局变量。global._ = require("underscore")因为我在每个文件中都要用到它。这是global的唯一用例。 - Raynos

44
根据@Raynos的回答,如果模块文件与包含它的文件在同一目录下,应该这样做。
var things = require("./someThings");
如果模块已经发布并通过npm安装,或者明确放置在./node_modules/文件夹中,则
var things = require("someThings");

是正确的。


4
如果您需要一个实际的节点模块(通过npm安装,在PROJECT_ROOT / node_modules下安装),则需要第二行代码。如果您需要引用自己的文件(即ROOT_DIR / models / thing.js),则需要执行第一行代码(尽管可以去掉.js扩展名)。 - Ankit Aggarwal
我不确定,但你可能可以使用 require 对象的 extensions 属性来更改这种行为。 (http://nodejs.org/api/globals.html#globals_require_extensions) - snapfractalpop

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