2012-10-05 17 views
7

Nel tentativo di rendere modulare un grande nodo esistente + espresso + Mongoose applicazione in più applicazioni montabili, ciascuno sviluppato come un pacchetto separato NPM , ci stiamo chiedendo se la condivisione di un unico Mongoose l'istanza tra loro è una buona idea?Condivisione di un'istanza Mongoose tra più NPM confeziona

Supponiamo di disporre di una suite di pacchetti NPM ciascuno contenente risorse lato client, modelli Mongoose e un'API REST implementata con Express. Esse condividono alcuni tratti comuni, ma sono essenzialmente da considerare separati artefatti riutilizzabili . Un'applicazione host, anche Express-based, monta questi sotto varie URI radice:

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

Ora, dal momento che le applicazioni events, tickets e discussions (separata NPM pacchetti tirato in via dell'ospite package.json) usare Mongoose, come facciamo l'applicazione host , abbiamo pensato di passare nell'istanza di Mongoose host attraverso una specie di oggetto environment che include anche altre cose che l'host vuole condividere con le app montate.

Vedete evidenti difetti con questo approccio? Le applicazioni montate in questo caso sarebbe non specificare Mongoose come dipendenza nel loro rispettive package.json, e avrebbero nonrequire('mongoose') come normalmente fatto ma invece ottenere l'istanza Mongoose dall'host che è responsabile per la connessione ad MongoDB.

Se questa è una cattiva idea e suggerire ogni sotto-app dichiarare una dipendenza verso Mongoose da soli, ogni pacchetto NPM otterrebbe la propria copia di Mongoose e avrebbe hanno ciascuno per connettersi a MongoDB, giusto?

Alcune informazioni di fondo:

  • Abbiamo davvero vogliamo includere le applicazioni in un'applicazione host, in esecuzione in un unico processo, piuttosto che avere più istanze Node. L'host contiene il middleware per l'autenticazione e altre cose.
  • Vogliamo che le app come pacchetti NPM sviluppati separatamente includano come dipendenze con versione delle varie applicazioni host che creiamo, anziché copiare semplicemente la loro origine in un'applicazione host.
  • Ci rendiamo conto che riutilizzando la stessa istanza Mongoose tra più app le condivideranno lo stesso spazio dei nomi del modello.

Edit: Per chiarire la struttura del pacchetto, dopo tutto è stato npm install ndr:

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

Cioè, il events, tickets e discussions applicazioni non includono Mongoose (o espresso) di ma sono progettati per fare affidamento su un'applicazione host sempre presente che fornisce tali dipendenze.

Presumiamo qui che un pacchetto NPM come tickets non può semplicemente essere fornito da require dal genitore, giusto?

risposta

6

Se si desidera riutilizzare il pacchetto Mongoose tra altri pacchetti NPM, il modo migliore per farlo è installare il pacchetto condiviso nell'app di livello superiore e quindi utilizzarlo per inizializzare gli altri pacchetti NPM.

Nel livello superiore:

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

Poi il pacchetto eventi ha solo bisogno di esportare una funzione che prende il db come parametro.

+0

Grazie mille per la risposta, ma non vuol dire che la questione centrale è solo spinto un livello di indirezione? Se ognuno dei nostri pacchetti NPM "installabile" include questo nuovo pacchetto "DB" come dipendenza, a un certo punto avranno tutti un'istanza Mongoose annidata ciascuno nei rispettivi 'node_modules' che devono essere tutti collegati a MongoDB? Il mio assunto attuale è che non è sufficiente che l'applicazione root/host dichiari una dipendenza verso questo pacchetto DB che i suoi altri pacchetti NPM possono 'richiedere'. Scusa se ti ho interpretato male. – Greg

+0

Oh scusa, ero confuso. Pensavo che stavi creando moduli riutilizzabili, non veri pacchetti NPM che stavi installando. NPM serve davvero per condividere pacchetti tra progetti, non creare moduli all'interno di un singolo progetto. Cosa speri di ottenere che l'utilizzo di moduli regolari non risolva? Sembrerebbe che tu stia duplicando un sacco di cose andando giù per il percorso di NPM. – Bill

+0

Aggiunto un piccolo chiarimento alla mia domanda. La logica dell'utilizzo dei pacchetti NPM è che sono facilmente dichiarati come dipendenze dell'host, in questo caso, con un semplice controllo delle versioni in modo che più host possano utilizzare versioni diverse della stessa sub-app direttamente dal suo 'package.json'. I pacchetti NPM attuali hanno i propri repository Git e cicli di sviluppo, ma suppongo che potremmo usare i sotto-moduli Git invece di gestirli attraverso l'host 'package.json'? O c'è un altro modo intelligente di riutilizzare i moduli? – Greg

3

Suggerisco di dare un'occhiata a https://github.com/jaredhanson/node-parent-require, un pacchetto pubblicato di recente che ha risolto questo problema per me.

Il node-parent-require Readme file nella pagina del progetto Github fornisce una panoramica dettagliata utilizzando mangusta.

In sostanza, è necessario scavare nel vostro modulo e sostituire questo:

mongoose = require("mongoose"); 

... con questo:

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

Non dimenticate di aggiungere mangusta come peerDependency in sottomodulo di package.json. Per esempio:

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

Si consiglia inoltre di leggere http://blog.nodejs.org/2013/02/07/peer-dependencies/ prima.

+0

Grandi articoli e la soluzione ha funzionato benissimo per me. Ho appena inserito il codice try..catch wrapper nel proprio file e tutti i pacchetti lo fanno riferimento - grazie! – electblake

+0

Come utilizzerei questo nel 2017 con importazioni ES6/Typescript? "import" non può essere racchiuso in un blocco try/catch ... –

Problemi correlati