2012-10-05 16 views
7

In einem Versuch, eine große vorhandenen Knoten + Express + Mongoose Anwendung in mehrere montierbaren Anwendungen, die jeweils als separaten NPM-Paket entwickelt modularisieren, ob fragen wir uns, einen einzigen Mongoose teilen Instanz zwischen ihnen ist eine gute Idee?eine Mongoose Instanz zwischen mehreren NPM Gemeinsame Nutzung Pakete

Nehmen wir an, wir haben eine Reihe von NPM-Paketen, die jeweils clientseitige Assets enthalten, Mongoose-Modelle und eine mit Express implementierte REST-API. Sie teilen ein paar gemeinsame Merkmale, sind aber im Wesentlichen als separate wiederverwendbare Artefakte betrachtet werden. Eine Host-Anwendung, auch Express-basierte, besteigt diese unter verschiedenen Root-URIs:

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

Jetzt, da die events, tickets und discussions Apps (getrennte NPM Pakete über den Host gezogen in package.json) verwenden Mungo, wie Tun Sie die Host-Anwendung selbst, dachten wir, wir würden in der Host-Mongoose-Instanz durch eine Art von environment Objekt, das auch andere Sachen, die der Host mit den bereitgestellten Apps teilen möchten gehören.

Sehen Sie irgendwelche offensichtlichen Mängel bei diesem Ansatz? Die montierten Apps in diesem Fall würde nicht angeben Mongoose als Abhängigkeit in ihrem jeweiligen package.json, und sie würden nichtrequire('mongoose') wie normalerweise getan, sondern die Mungo-Instanz aus dem Host erhalten, die für den Anschluss an verantwortlich MongoDB.

Wenn dies eine schlechte Idee ist, und schlagen Sie vor jedem Unter App eine Abhängigkeit Richtung Mongoose auf ihrem eigenen erklären, jedes Paket NPM ihre eigene Kopie von Mongoose bekommen und würde jeweils zu MongoDB verbinden, nicht wahr?

Einige Hintergrundinfo:

  • wir wirklich tun wollen, um die Anwendungen in einer Host-Anwendung enthalten, in einem einzigen Prozess ausgeführt wird, sondern dass mehrere Knoten Instanzen haben. Der Host enthält Middleware für die Authentifizierung und andere Dinge.
  • Wir möchten die Apps als separat entwickelte NPM-Pakete enthalten als versionierte Abhängigkeiten der verschiedenen Host-Anwendungen, die wir erstellen, anstatt nur ihre Quelle zu einer Host-Anwendung zu kopieren.
  • Wir wissen, dass die Wiederverwendung der gleichen Mongoose-Instanz zwischen mehreren gemounteten Anwendungen haben sie den gleichen Modell-Namespace teilen.

Edit: die Paketstruktur Um zu klären, nachdem alle war npm install ed:

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

Das heißt, die events, tickets und discussions Apps nicht enthalten Mongoose (oder Express) von ihre eigenen, aber sind entworfen, um auf einer immer vorhandenen Host-Anwendung, die diese Abhängigkeiten liefert zu verlassen.

Wir gehen hier davon aus, dass ein NPM-Paket wie tickets kann nicht einfach require Zeug von der Eltern, richtig?

Antwort

6

Wenn Sie Ihr Mongoose-Paket zwischen anderen NPM-Paketen wiederverwenden möchten, installieren Sie das freigegebene Paket in der App auf oberster Ebene und verwenden Sie es dann zum Initialisieren der anderen NPM-Pakete.

In der obersten Ebene:

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

Dann Ihre Events Paket benötigt nur eine Funktion zu exportieren, die die DB als Parameter annimmt.

+0

Vielen Dank für Ihre Antwort, aber heißt das nicht, dass die Kernfrage einen Dereferenzierungsebene gerade gedrückt wird? Wenn jedes unserer "mountable app" NPM-Pakete dieses neue "DB" -Paket als Abhängigkeit enthält, haben sie irgendwann einmal eine verschachtelte Mongoose-Instanz in ihren jeweiligen 'node_modules', die alle mit MongoDB verbunden sein müssen? Meine derzeitige Annahme ist, dass es für die root/host-Anwendung nicht ausreicht, eine Abhängigkeit zu diesem DB-Paket zu deklarieren, die seine anderen NPM-Pakete "benötigen". Entschuldige, wenn ich dich falsch verstanden habe. – Greg

+0

Oh Entschuldigung, ich war verwirrt. Ich dachte, Sie würden nur wiederverwendbare Module erstellen, nicht tatsächliche NPM-Pakete, die Sie installiert haben. NPM ist wirklich für das Teilen von Paketen zwischen Projekten, nicht das Erstellen von Modulen in einem einzelnen Projekt. Was erhoffen Sie sich zu gewinnen, dass sich mit regulären Modulen nicht lösen lässt? Es scheint mir, dass du viele Dinge duplizieren wirst, die den NPM-Weg hinunter gehen. – Bill

+0

Eine kleine Erläuterung zu meiner Frage hinzugefügt. Die Gründe für die Verwendung von NPM-Paketen liegen darin, dass sie leicht als Abhängigkeiten des Hosts deklariert werden können, in diesem Fall durch einfache Versionierung, so dass mehrere Hosts verschiedene Versionen derselben Sub-App direkt aus ihrer 'package.json' verwenden können. Die eigentlichen NPM-Pakete haben ihre eigenen Git-Repos und Entwicklungslebenszyklen, aber ich denke, wir könnten Git-Untermodule verwenden, anstatt sie über den Host 'package.json' zu verwalten. Oder gibt es eine weitere clevere Möglichkeit, Module wiederzuverwenden? – Greg

3

Ich schlage vor, Sie sehen https://github.com/jaredhanson/node-parent-require, ein kürzlich veröffentlichtes Paket, das dieses Problem für mich gelöst hat.

Die node-parent-require Readme file auf der Github-Projektseite bietet eine detaillierte Walkthrough mit Mungo.

Grundsätzlich müssen Sie in Ihrem Modul graben und ersetzen diese:

mongoose = require("mongoose"); 

... mit diesem:

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

nicht Mungo als peerDependency im Submodul ist hinzuzufügen Vergessen Paket.json. Zum Beispiel:

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

Sie können auch zuerst http://blog.nodejs.org/2013/02/07/peer-dependencies/ lesen möchten.

+0

Große Artikel, und Lösung hat gut für mich gearbeitet. Ich habe nur den try..catch wrapper Code in eine eigene Datei geschrieben, und alle Pakete verweisen darauf - danke! – electblake

+0

Wie würde ich das 2017 mit ES6/Typescript-Importen verwenden? "import" kann nicht in einen try/catch-Block gehüllt werden ... –

Verwandte Themen