Wie kann ich Code zwischen node.js Apps teilen?

77

Ich habe mehrere Apps im Knoten, die alle einige Module gemeinsam nutzen, die ich geschrieben habe. Diese Module sind nicht über npm verfügbar. Ich möchte in der Lage sein, frei zwischen Apps zu teilen, aber ich möchte keine Verzeichnisse kopieren oder mich darauf verlassen, dass Git dies tut. Und ich bin auch nicht besonders begeistert davon, Symlinks zu verwenden, um dies zu tun.

Ich möchte Verzeichnisse wie folgt anordnen:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
 lib
  (my own modules specific to app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
 lib
  (my own modules specific to app2)

shared_lib
 (my own modules that are used in both app1 and app2)

Das Problem, das ich sehe, ist, dass die Module in shared_lib verwirrt zu sein scheinen, wo sich die Module befinden, die sich im Verzeichnis node_modules der App befinden, in der sie ausgeführt werden. Zumindest denke ich, dass dies das Problem ist.

Also ... was ist ein guter Weg, um Duplikate von Dateien zu vermeiden? (Beachten Sie, dass ich mich nicht um Duplikate von Dingen in node_modules kümmere, da diese nicht mein Code sind und ich sie nicht in Git usw. einchecke.)

rauben
quelle

Antworten:

22

Ich habe dies funktioniert, indem ich node_modules- Ordner auf verschiedenen Ebenen habe - node geht dann automatisch nach oben, bis es das Modul findet.

Beachten Sie, dass Sie nicht in npm veröffentlichen müssen, um ein Modul in node_modules zu haben. Verwenden Sie einfach:

"private": true

In jeder Ihrer privaten package.json- Dateien hätte ich für Ihr Projekt Folgendes:

app1
 server.js
 node_modules
  (public modules from npm needed for app1)
  (private modules locally needed for app1)

app2
 server.js
 node_modules
  (public modules from npm needed for app2)
  (private modules locally needed for app2)

node_modules
  (public modules from npm needed for app1 & app2)
  (private modules locally for app1 & app2)

Der Punkt ist, node.js hat bereits einen Mechanismus, um damit umzugehen, und es ist fantastisch. Kombinieren Sie es einfach mit dem Trick "Privat nicht auf NPM" und Sie können loslegen.

Kurz gesagt:

require('somemodule')

Von App A oder B würde es nach oben kaskadieren, bis es das Modul gefunden hat - unabhängig davon, ob es tiefer oder höher lebte. Auf diese Weise können Sie den Speicherort im laufenden Betrieb austauschen, ohne die erforderlichen (...) Anweisungen zu ändern .

Dokumentation zum Modul node.js.

Bino Carlos
quelle
8
Als ich dies versuchte, konnten alle für die gemeinsam genutzten Module erforderlichen Module nicht aufgelöst werden. In Ihrer Struktur sieht es so aus, als ob der höchste Ordner "node_modules" sowohl private (in die Quellcodeverwaltung eingecheckt) als auch öffentliche (npm install'd - nicht eingecheckt) Module enthält. Normalerweise überprüfe ich öffentliche Module nicht in der Quellcodeverwaltung - wie sind Sie damit umgegangen?
Adam C
47

In der npm-Dokumentation wird empfohlen, npm-link zu verwenden, um Ihre eigenen Node.js-Pakete lokal zu erstellen und sie dann anderen Node.js-Anwendungen zur Verfügung zu stellen. Es ist ein einfacher vierstufiger Prozess.

Ein typisches Verfahren wäre, zuerst ein Paket mit der folgenden Struktur zu erstellen:

  hello
  | index.js
  | package.json

Eine typische Implementierung dieser Dateien wäre:

index.js

  exports.world = function() {
     return('Hello World');
  }

package.json

  {
    "name": "hello",
    "version": "0.0.1",
    "private": true,
    "main": "index.js",
    "dependencies": {
    },
    "engines": {
    "node": "v0.6.x"
    }
  }

"private: true" stellt sicher, dass npm die Veröffentlichung des Pakets verweigert. Dies ist eine Möglichkeit, die versehentliche Veröffentlichung privater Pakete zu verhindern.

Navigieren Sie als Nächstes zum Stammverzeichnis Ihres Node.js-Paketordners und führen Sie es aus npm link, um das Paket global zu verknüpfen, damit es in anderen Anwendungen verwendet werden kann.

So verwenden Sie dieses Paket in einer anderen Anwendung, z. B. "Hallo Welt", mit der folgenden Verzeichnisstruktur:

 hello-world
 | app.js

Navigieren Sie zum Ordner "Hallo Welt" und führen Sie Folgendes aus:

 npm link hello

Jetzt können Sie es wie jedes andere npm-Paket wie folgt verwenden:

app.js.

  var http = require('http');
  var hello = require('hello');

  var server = http.createServer(function(req, res) {
     res.writeHead(200);
     res.end(hello.world());
  });
  server.listen(8080);
almypal
quelle
6
Wie funktioniert dies bei der Bereitstellung in einer PaaS-Umgebung wie Heroku oder Nodejitsu?
Adam C
npm link funktioniert in einer PaaS-Umgebung nicht. Heroku berücksichtigt Knotenmodule, die mit Ihrem Code eingegeben werden. Das könnte also eine Option sein.
Almypal
1
Das bekomme ich nicht - wenn Sie von git aus auf Heroku bereitstellen, checken Sie Ihre node_modules nicht ein. Außerdem würde dies bedeuten, dass Sie Ihren freigegebenen Code vor dem Einchecken in den Ordner node_modules kopieren. Dies scheint umständlich und fehlerhaft zu sein anfällig. Oder fehlt mir etwas? Vielen Dank!
Adam C
Das scheint der einzige Ausweg zu sein. Die Option npm link ist nur verfügbar, wenn Sie über ssh Zugriff auf das Remote-Terminal haben ... wie in AWS oder Rackspace
almypal
1
Ich denke, Sie können Webpack verwenden, um das Ganze für diesen Zweck zusammen zu verpacken
Georgii Oleinikov
4

Verwenden Sie einfach den richtigen Pfad in Ihrem gewünschten Anruf

Zum Beispiel in server.js wäre das:

var moduleName = require ('../ shared_lib / moduleName / module.js');

Es ist wichtig zu wissen, dass der Pfad relativ zur aufrufenden Datei ist, sobald Ihrem Pfad '/', '../' oder './' vorangestellt ist.

Weitere Informationen zum Laden von Knotenmodulen finden Sie unter: http://nodejs.org/docs/latest/api/modules.html

Taner Topal
quelle
8
Aber wenn ich das mache und dieses Modul dann versucht, ein Modul zu benötigen, das von npm kommt, wird es verwirrt und gibt Fehler.
Rob
1
keine Antwort? Das liegt daran, dass Sie versucht haben, mit Node
Toolkit
4

Ja, Sie können auf shared_lib von app1 aus verweisen, aber dann tritt ein Problem auf, wenn Sie app1 in einer anderen Umgebung, z. B. einem Webserver in AWS, verpacken und bereitstellen möchten.

In diesem Fall ist es besser, Ihre Module in shared_lib auf app1 und app2 mit "npm install shared_lib / module" zu installieren. Außerdem werden alle Abhängigkeiten der shared_lib-Module in App1 und App2 installiert und Konflikte / Duplikate behandelt.

Siehe dies: Wie installiere ich ein privates NPM-Modul ohne meine eigene Registrierung?

Mohamed Fakhreddine
quelle
2

Wenn Sie die Dokumente von node.js auschecken , werden Sie feststellen , dass Node.js das package.jsonDateiformat zumindest flüchtig versteht.

Wenn Sie ein Verzeichnis mit dem Namen foohaben und sich in diesem Verzeichnis eine package.jsonDatei mit dem Schlüssel-Wert-Paar befindet: "main": "myCode.js"Wenn Sie versuchen, require("foo")dieses Verzeichnis mit einer darin enthaltenen package.jsonDatei zu finden, wird es foo/myCode.jsfür das fooModul verwendet.

Wenn also in Ihrer Verzeichnisstruktur jede gemeinsam genutzte Bibliothek ein eigenes Verzeichnis mit einer so einfachen package.jsonDatei enthält, können Ihre Apps die gemeinsam genutzten Bibliotheken abrufen, indem Sie:

var lib1 = require('../shared_lib/lib1');
var lib2 = require('../shared_lib/lib2');

Und das sollte für beide Apps funktionieren.


quelle