9

为了将现有的大型 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));

现在,由于events,ticketsdiscussions应用程序(通过主机拉入的单独 NPM 包package.json)使用 Mongoose,主机应用程序本身也是如此,我们认为我们将通过某种environment对象传递主机 Mongoose 实例,该对象还包括主机的其他内容想与已安装的应用程序共享。

您是否发现这种方法有任何明显的缺陷?在这种情况下,挂载的应用程序不会将 Mongoose 指定为它们各自的依赖项package.json,并且它们不会 require('mongoose') 像往常那样做,而是从负责将其连接到 MongoDB 的主机获取 Mongoose 实例。

如果这是一个坏主意,并且您建议每个子应用程序自己声明对 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/ ...

也就是说eventstickets、 和discussions应用程序不包含它们自己的 Mongoose(或 Express),而是设计为依赖于提供这些依赖项的始终存在的主机应用程序。

我们在这里假设像 NPM 包这样的 NPM 包tickets不能简单地 require来自父级,对吗?

4

3 回答 3

7

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

在顶层:

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

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

于 2012-10-05T22:28:59.873 回答
3

我建议你看看https://github.com/jaredhanson/node-parent-require,这是一个最近发布的包,它为我解决了这个问题。

Github 项目页面上的node-parent-require 自述文件提供了使用 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/

于 2013-09-06T10:15:03.010 回答
0
const mongoose = require('mongoose-global')();

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

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

于 2017-08-04T19:01:49.463 回答