2012-10-05 12 views
7

Próbując zmodularyzowanie dużą istniejącego węzła + ekspresowe + Mongoose aplikacji w wielu aplikacjach, montowany każdy opracowany jako oddzielny pakiet NPM, że zastanawiasz się, czy dzieląc pojedynczy Mongoose przykład między nimi jest dobrym pomysłem?Udostępnianie Mongoose instancji między wieloma KMP pakiety

Załóżmy, że mamy pakiet pakietów NPM, z których każdy zawiera zasoby po stronie klienta, Modele Mongoose i REST-API zaimplementowany w Express. Dzielą one kilka wspólnych cech, ale zasadniczo są uważane za osobne artefakty wielokrotnego użytku. Aplikacja hosta, także ekspresowe opartych montuje te pod różnymi URI root:

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

Teraz, ponieważ events, tickets i discussions aplikacji (oddzielny NPM pakiety wciągnięta przez przyjmującego package.json) używać Mongoose, jak Zrobiliśmy aplikację hosta i pomyśleliśmy, że przejdziemy do instancji Mongoose hosta za pośrednictwem jakiegoś obiektu environment, który obejmuje również inne rzeczy, które host chce udostępnić zainstalowanym aplikacjom.

Czy widzisz jakieś oczywiste wady tego podejścia? Zamontowane aplikacje w tym przypadku byłoby nie określić Mongoose jako zależność w ich odpowiedniego package.json, a oni by nierequire('mongoose') jak zwykle zrobić, ale zamiast otrzymać instancję Mongoose z hosta który jest odpowiedzialny za podłączenie do MongoDB.

Jeśli jest to zły pomysł i sugerują każdy sub-app zadeklarować zależność kierunku Mongoose na własną rękę, każdy pakiet NPM dostanie własną kopię Mangusta i każdy będzie musiał połączyć się MongoDB, prawda?

Niektóre informacje tła:

  • Naprawdę chcesz zawierać aplikacje w aplikacji hosta, bieganie w jednym procesie, raczej, że o wiele wystąpień węzła. Host zawiera oprogramowanie pośrednie do uwierzytelniania i inne rzeczy.
  • Chcemy, aby aplikacje jako oddzielnie opracowane pakiety NPM zawierały jako zależne od wersji zależności różnych aplikacji hosta, które budujemy, , a nie tylko kopiowanie ich źródła do aplikacji hosta.
  • Zdajemy sobie sprawę, że ponowne użycie tej samej instancji Mongoose między wieloma zainstalowanymi aplikacjami spowoduje, że będą one miały ten sam model przestrzeni nazw.

Edit: Aby wyjaśnić strukturę pakietów mimo wszystko został npm install ed:

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

Oznacza to, że events, tickets i discussions aplikacje nie zawierają Mongoose (lub Express) z własne, ale są zaprojektowane tak, aby polegać na zawsze aktualnej aplikacji hosta, która dostarcza tych zależności.

Zakładamy, że pakiet NPM taki jak tickets nie może po prostu require rzeczy od rodzica, prawda?

Odpowiedz

6

Jeśli chcesz ponownie wykorzystać pakiet Mongoose między innymi pakietami NPM, najlepszym sposobem jest zainstalowanie udostępnionego pakietu w aplikacji najwyższego poziomu, a następnie użycie go do zainicjowania innych pakietów NPM.

W górnym poziomie:

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

Następnie pakiet zdarzenia po prostu musi eksportować funkcję, która pobiera db jako parametr.

+0

dziękuję za odpowiedź, ale nie oznacza to, że kluczową kwestią jest po prostu popchnął jednego poziomu zadnie? Jeśli każdy z pakietów NPM "mountable app" zawiera ten nowy pakiet "DB" jako zależność, wszystkie będą miały w pewnym momencie zagnieżdżone instancję Mongoose, każdy w swoich "node_modules", które wszystkie muszą być podłączone do MongoDB? Moje obecne założenie jest takie, że nie wystarczy, aby aplikacja root/host zadeklarowała zależność od tego pakietu DB, którego inne pakiety NPM mogą "wymagać". Przepraszam, jeśli źle cię zrozumiałem. – Greg

+0

Przepraszam, byłem zdezorientowany. Myślałem, że tworzysz tylko moduły wielokrotnego użytku, a nie rzeczywiste pakiety NPM, które instalujesz. NPM jest naprawdę do dzielenia pakietów między projektami, nie tworząc modułów w ramach jednego projektu. Co masz nadzieję osiągnąć, używając zwykłych modułów, których nie rozwiążesz? Wydaje mi się, że będziesz duplikował wiele rzeczy idących ścieżką NPM. – Bill

+0

Dodałem małe wyjaśnienie do mojego pytania. Uzasadnieniem dla korzystania z pakietów NPM jest to, że są one łatwo deklarowane jako zależności hosta, w tym przypadku z prostą wersją, tak aby wiele hostów mogło korzystać z różnych wersji tej samej sub-aplikacji bezpośrednio z jego 'package.json'. Rzeczywiste pakiety NPM mają swoje własne repozytoria Git i cykle rozwojowe, ale myślę, że moglibyśmy użyć podmodułów Git zamiast zarządzać nimi przez hosta 'pakiet.json'? Czy istnieje inny inteligentny sposób ponownego wykorzystania modułów? – Greg

3

Proponuję zapoznać się z https://github.com/jaredhanson/node-parent-require, ostatnio opublikowanym pakietem, który rozwiązał dla mnie ten problem.

Na stronie projektu Github znajduje się szczegółowy opis przejścia za pomocą mangusty.

Zasadniczo trzeba kopać w swoim modułem i zastąpić to:

mongoose = require("mongoose"); 

... z tym:

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

Nie zapomnij dodać mongoose jako peerDependency w swoim modułem roku package.json. Na przykład:

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

Najpierw możesz również przeczytać http://blog.nodejs.org/2013/02/07/peer-dependencies/.

+0

Świetne artykuły i rozwiązanie sprawdziło się doskonale. Właśnie umieszczam kod opakowania try..catch we własnym pliku, a wszystkie pakiety go odwołują - dzięki! – electblake

+0

Jak tego użyć w 2017 roku z importem ES6/maszynowym? "import" nie może być zawijany w bloku try/catch ... –

Powiązane problemy