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

为了将现有的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应用程序(通过主机package.json单独的NPM包)使用Mongoose,就像主机应用程序本身一样,我们想通过某种environment对象传递主机Mongoose实例还包括主机想要与安装的应用程序共享的其他东西。

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

如果这是一个坏主意,你build议每个子应用程序自己声明一个对Mongoose的依赖,每个NPM软件包将获得自己的Mongoose副本,每个都必须连接到MongoDB,对不对?

一些背景信息:

  • 我们确实希望将这些应用程序包含在一个宿主应用程序中,在一个进程中运行,而不是拥有多个Node实例。 主机包含用于authentication和其他事情的中间件。
  • 我们希望将这些应用作为独立开发的NPM软件包,作为我们构build的各种主机应用程序的版本化依赖项,而不仅仅是将其源代码复制到主机应用程序。
  • 我们认识到,在多个安装的应用程序之间重复使用相同的Mongoose实例将使它们共享相同的模型名称空间。

编辑:为了澄清包装结构之后所有的npm install ed:

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

也就是说, eventsticketsdiscussions应用程序不包含自己的Mongoose(或Express),而是被devise为依赖总是存在的主机应用程序来提供这些依赖关系。

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

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

在顶层:

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

那么你的事件包只需要导出一个函数,把db作为参数。

我build议你看看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/

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

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

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