在多个NPM包之间共享Mongoose实例

时间:2012-10-05 22:00:05

标签: node.js express mongoose npm

试图模块化现有的大型Node + Express + Mongoose 应用到多个可安装的应用程序,每个应用程序开发为 单独的NPM包,我们想知道是否共享一个 他们之间的Mongoose实例是个好主意?

假设我们有一套NPM包,每个包含客户端资产, Mongoose模型和使用Express实现的REST-API。他们分享 一些共同的特征,但基本上被认为是分开的 可重复使用的文物。主机应用程序也是基于Express的,可以安装这些应用程序 在各种根URI下:

var discussions = require('discussions'),
    tickets     = require('tickets'),
    events      = require('events'),
    express     = require('express'),
    app         = express();

var environment = { ...see below... };

...

app.use('/events-api', events(environment));
app.use('/tickets-api', tickets(environment));
app.use('/discussions-api', discussions(environment));

现在,由于eventsticketsdiscussions个应用(单独的NPM包) 通过主机package.json拉入)使用Mongoose,就像使用 主机应用程序本身,我们想通过主机Mongoose实例传递 通过某种environment对象,也包括其他对象 主持人希望与已安装的应用共享的内容。

你认为这种方法存在明显的缺陷吗?已安装的应用 在这种情况下,将Mongoose指定为其中的依赖项 各自package.json,他们 require('mongoose') 正常情况下,但从主机获取Mongoose实例 负责将其连接到MongoDB。

如果这是一个坏主意,您建议每个子应用程序声明一个依赖项 对于Mongoose而言,每个NPM包都会得到自己的 Mongoose的副本,每个都必须连接到MongoDB,对吗?

一些背景信息:

  • 我们确实希望将应用程序包含在运行的主机应用程序中 在一个进程中,而不是具有多个Node实例。该 主机包含用于身份验证和其他事物的中间件。
  • 我们确实希望将应用程序作为单独开发的NPM软件包包含在内 作为我们构建的各种主机应用程序的版本化依赖项, 而不是仅将其源代码复制到主机应用程序。
  • 我们意识到在多个之间重用相同的Mongoose实例 安装的应用程序将使它们共享相同的模型命名空间。

修改:在npm install编辑完所有内容后澄清包结构:

host/
  assets/
  models/
  routes/
  node_modules/
    express/ ...
    mongoose/ ...
    events/
      assets/ ...
      models/ ...
      routes/ ...
    tickets/
      assets/ ...
      models/ ...
      routes/ ...
    discussions/
      assets/ ...
      models/ ...
      routes/ ...

也就是说,eventsticketsdiscussions应用不包含在内 Mongoose(或Express)属于他们自己但设计依赖于永远存在的 提供这些依赖项的主机应用程序。

我们在此假设像tickets这样的NPM包不能简单 来自父母的require东西,对吧?

3 个答案:

答案 0 :(得分:6)

如果要在其他NPM包之间重用Mongoose包,最好的方法是在顶级应用程序中安装共享包,然后使用它来初始化其他NPM包。

在顶层:

var db = require('myMongooseDb'),
    events = require('events')(db),
    ...

然后你的事件包只需要导出一个以db作为参数的函数。

答案 1 :(得分:3)

我建议您查看https://github.com/jaredhanson/node-parent-require,这是最近发布的一个解决了这个问题的方法。

Github项目页面上的node-parent-require Readme file提供了使用mongoose的详细演练。

基本上,您需要挖掘子模块并替换它:

mongoose = require("mongoose");

......用这个:

try {
  var mongoose = require('mongoose');
} catch (_) {
  // workaround when `npm link`'ed for development
  var prequire = require('parent-require')
    , mongoose = prequire('mongoose');
}

不要忘记在子模块的package.json中添加mongoose作为peerDependency。例如:

"peerDependencies": {
  "mongoose": "3.x"
}

您可能还想先阅读http://blog.nodejs.org/2013/02/07/peer-dependencies/

答案 2 :(得分:0)

const mongoose = require('mongoose-global')();

您可以只需要一个全局的mongoose实例并在任何地方使用它。

https://www.npmjs.com/package/mongoose-global