如何在Node.js应用之间共享代码?


77

我在节点中有几个应用程序,都共享我编写的一些模块。这些模块无法通过npm获得。我希望能够在应用程序之间自由共享,但是我不想复制目录,也不想依靠Git这样做。我也不是很乐意使用符号链接来做到这一点。

我想安排这样的目录:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
 lib
  (my own modules specific to app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
 lib
  (my own modules specific to app2)

shared_lib
 (my own modules that are used in both app1 and app2)

我看到的问题是,shared_lib中的模块似乎对于在哪里找到要运行的应用程序的node_modules目录中的模块感到困惑。至少我认为这是问题所在。

所以....什么是避免重复文件的好方法?(请注意,我不在乎node_modules中的重复项,因为这些不是我的代码,因此我不会将它们检入Git等)

Answers:


22

我通过在不同级别使用node_modules文件夹来完成此工作-节点然后自动向上遍历直到找到模块。

请注意,您不必发布到npm即可在node_modules中包含模块-只需使用:

"private": true

在每个私有的package.json文件中-对于您的项目,我将具有以下内容:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
  (private modules locally needed for app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
  (private modules locally needed for app2)

node_modules
  (public modules from npm needed for app1 & app2)
  (private modules locally for app1 & app2)

关键是node.js已经有一种机制可以解决这个问题,而且很棒。只需将其与“不使用NPM的私人”技巧结合在一起,您就可以开始使用了。

简而言之:

require('somemodule')

从应用程序A或B向上层叠,直到找到模块-不管它住得较低还是较高。确实-这使您可以在不更改任何require(...)语句的情况下热交换位置。

node.js模块文档


8
当我尝试此操作时,共享模块所需的任何模块都无法解析。在您的结构中,看起来最高的node_modules文件夹同时具有专用(已签入源代码管理)和公用(npm install'd-未签入)模块。我通常不会将公共模块检入源代码控制中-您是如何解决这个问题的?
亚当C

47

npm文档建议使用npm-link在本地创建自己的Node.js程序包,然后将其提供给其他Node.js应用程序。这是一个简单的四步过程。

典型的过程是首先创建具有以下结构的包:

  hello
  | index.js
  | package.json

这些文件的典型实现为:

index.js

  exports.world = function() {
     return('Hello World');
  }

package.json

  {
    "name": "hello",
    "version": "0.0.1",
    "private": true,
    "main": "index.js",
    "dependencies": {
    },
    "engines": {
    "node": "v0.6.x"
    }
  }

“ private:true”确保npm拒绝发布该程序包。这是防止意外发布私有软件包的方法。

接下来,导航到Node.js软件包文件夹的根目录并运行npm link以全局链接该软件包,以便可以在其他应用程序中使用它。

要在具有以下目录结构的另一个应用程序(例如“ hello-world”)中使用此软件包:

 hello-world
 | app.js

导航到hello-world文件夹并运行:

 npm link hello

现在,您可以像使用任何其他npm软件包一样使用它:

app.js

  var http = require('http');
  var hello = require('hello');

  var server = http.createServer(function(req, res) {
     res.writeHead(200);
     res.end(hello.world());
  });
  server.listen(8080);

6
部署到诸如Heroku或Nodejitsu之类的PaaS环境时,这如何工作?
亚当C

npm链接在PaaS环境中不起作用。Heroku尊重随您的代码推送的节点模块。因此,这可能是一个选择。
13年

1
那就是我没有得到的-如果您从git部署到Heroku,则不要签入您的node_modules。而且,这意味着您在签入之前将共享代码复制到node_modules文件夹中。这看起来很麻烦且出错容易 还是我错过了什么?谢谢!
亚当C

那似乎是唯一的出路。仅当您可以通过ssh访问远程终端时,才可使用npm link选项。例如在AWS或Rackspace中
almypal,2013年

1
我认为您可以为此目的使用webpack将整个内容打包在一起
Georgii Oleinikov

4

只需在您的require呼叫中使用正确的路径

例如在server.js中将是:

var moduleName = require('../ shared_lib / moduleName / module.js');

重要的是要知道,只要您的路径以'/'、'../'或'./'作为前缀,路径就相对于调用文件。

有关节点模块加载的更多信息,请访问:http : //nodejs.org/docs/latest/api/modules.html


8
但是,如果我这样做,然后该模块尝试要求使用来自npm的模块,则会感到困惑并给出错误。

1
没有答案?那是因为您试图用Node构建一个比演示更复杂的东西
Toolkit

4

是的,您可以从app1引用shared_lib,但是如果要将app1打包并部署到其他环境(例如AWS上的Web服务器),则会遇到问题。

在这种情况下,最好使用“ npm install shared_lib / module”将shared_lib中的模块安装到app1和app2中。它还将在app1和app2中安装shared_lib模块的所有依赖项,并处理冲突/重复项。

请参阅以下内容: 如何在没有我自己的注册表的情况下安装私有NPM模块?


2

如果签出node.js文档,您会发现Node.jspackage.json至少也可以理解文件格式。

基本上,如果您有一个名为的目录foo,并且在该目录中是一个package.json具有键-值对的文件:"main": "myCode.js",那么如果尝试这样做require("foo"),它将在其中找到一个package.json包含文件的目录,则它将foo/myCode.js用于该foo模块。

因此,对于您的目录结构,如果每个共享库都具有自己的目录,并且package.json内部包含一个简单文件,则您的应用程序可以通过以下方式获取共享库:

var lib1 = require('../shared_lib/lib1');
var lib2 = require('../shared_lib/lib2');

这对这两个应用程序都适用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.