2012-10-05 28 views
7

En un intento de modularizar un gran nodo existente + express + Mangosta aplicación en múltiples aplicaciones montables, cada uno desarrollado como un paquete separado NPM , nos preguntamos si compartir una única Mangosta ejemplo entre ellos es una buena idea?compartir una instancia Mangosta entre múltiples paquetes NPM

Digamos que tenemos un conjunto de paquetes NPM que contienen activos del lado del cliente, modelos Mongoose y una REST-API implementada con Express. Comparten algunos rasgos comunes, pero se consideran como artefactos reutilizables por separado. Una aplicación host, también a base de expreso, monta estos bajo varias URI raíz:

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)); 

Ahora, ya que los events, tickets y discussions aplicaciones (separado NPM paquetes introducirá mediante el anfitrión package.json) utiliza Mangosta, como hacer la aplicación de host en sí, pensamos que pasaríamos en la instancia Mongoose de host a través de algún tipo de objeto environment que también incluye otras cosas que el host desea compartir con las aplicaciones montadas.

¿Ve algún defecto obvio con este enfoque? Las aplicaciones montadas en este caso serían no especificar Mangosta como una dependencia en su respectiva package.json, y lo harían norequire('mongoose') como se hace normalmente, pero en lugar de obtener la instancia Mangosta desde el host que es responsable de la conexión a MongoDB.

Si esto es una mala idea y que sugieren cada sub-aplicación declarar una dependencia hacia Mangosta por su cuenta, cada paquete NPM conseguiría su propia copia de Mangosta y que cada uno tiene que conectarse a MongoDB, ¿verdad?

Algunos información de fondo:

  • Realmente queremos incluir las aplicaciones en una aplicación host, corriendo en un solo proceso, en lugar de que tener varias instancias de nodo. El host contiene middleware para la autenticación y otras cosas.
  • Queremos tener las aplicaciones como paquetes NPM desarrollados por separado que incluyen como dependencias versionadas de las diversas aplicaciones host que creamos, en lugar de simplemente copiar su fuente a una aplicación de host.
  • Nos damos cuenta de que la reutilización de la misma instancia de Mongoose entre varias aplicaciones montadas en hará que compartan el mismo espacio de nombres de modelo.

Editar: Para aclarar la estructura del paquete después de todo ha sido npm install ed:

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

Es decir, el events, tickets y discussions aplicaciones no incluyen Mangosta (o Express) de propios pero están diseñados para confiar en una aplicación de host siempre presente que suministra esas dependencias.

Estamos asumiendo aquí que un paquete de NPM como tickets no puede simplemente require cosas del padre, ¿verdad?

Respuesta

6

Si desea reutilizar su paquete Mongoose entre otros paquetes NPM, la mejor manera de hacerlo es instalar el paquete compartido en la aplicación de nivel superior y luego usarlo para inicializar los otros paquetes NPM.

En el nivel superior:

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

A continuación, el paquete de eventos sólo tiene que exportar una función que toma el PP como parámetro.

+0

Muchas gracias por su respuesta, pero no se que quiere decir que la raíz del problema es simplemente empujó un nivel de indirección? Si cada uno de nuestros paquetes de NPM de la "aplicación montable" incluye este nuevo paquete "DB" como dependencia, todos ellos en algún momento tendrán una instancia de Mongoose anidada, cada uno en sus respectivos 'node_modules', que todos deben estar conectados a MongoDB. Mi suposición actual es que no es suficiente que la aplicación raíz/host declare una dependencia hacia este paquete DB que sus otros paquetes NPM pueden 'requerir'. Lo siento si te malinterpreté. – Greg

+0

Oh, lo siento, estaba confundido. Pensé que solo estabas creando módulos reutilizables, no paquetes de NPM reales que estabas instalando. NPM es realmente para compartir paquetes entre proyectos, no para crear módulos dentro de un solo proyecto. ¿Qué esperas obtener con módulos regulares que no resuelven? Me parece que estarás duplicando muchas cosas yendo por el camino de NPM. – Bill

+0

Agregué una pequeña aclaración a mi pregunta. La razón para usar paquetes de NPM es que se declaran fácilmente como dependencias del host, en este caso, con versiones simples para que múltiples hosts puedan usar diferentes versiones de la misma sub-aplicación directamente desde su 'package.json'. Los paquetes reales de NPM tienen sus propios repositorios de Git y ciclos de vida de desarrollo, pero supongo que podríamos usar los submódulos de Git en lugar de administrarlos a través del host 'package.json'. ¿O hay otra forma inteligente de reutilizar módulos? – Greg

3

Sugiero que eche un vistazo a https://github.com/jaredhanson/node-parent-require, un paquete recientemente publicado que resolvió este problema para mí.

El node-parent-require Readme file en la página del proyecto Github proporciona un recorrido detallado utilizando mangosta.

Básicamente, hay que cavar en su submódulo y reemplazar esto:

mongoose = require("mongoose"); 

... con esto:

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

No se olvide de añadir mangosta como peerDependency en sus submódulo de paquete.json. Por ejemplo:

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

También puede leer http://blog.nodejs.org/2013/02/07/peer-dependencies/ primero.

+0

Grandes artículos, y la solución funcionó muy bien para mí. Acabo de poner el código try..catch wrapper en un archivo propio, y todos los paquetes lo hacen referencia, ¡gracias! – electblake

+0

¿Cómo utilizaría esto en 2017 con las importaciones de ES6/Typescript? "Importar" no puede ser envuelto en un bloque try/catch ... –

Cuestiones relacionadas