Node: mehrere Services lokal starten
Node macht die ersten zwei Services leicht: zweimal npm start und du
arbeitest. Der Ärger kommt mit dem vierten Terminal, mit dem zweiten Service, der auch Port
3000 will, und mit dem Paket, das du gleichzeitig mit dem Service änderst, der es benutzt.
Was zuerst bricht
- Die Terminals. Eines pro Service, jedes mit seiner Umgebung, und ohne Erinnerung daran, welche Kombination gestern funktioniert hat.
- Die Ports. Alles bringt standardmäßig 3000 mit. Du endest mit einer
.envpro Entwicklerin, die nie committet und nie dokumentiert wird. - Die URLs zwischen den Services. Jedes
fetchauf einen anderen Service liest eine Variable, und drei davon auf die gemeinsame Umgebung zeigen zu lassen heißt, Dateien zu ändern, die du nicht committen darfst. - Das lokale Paket.
npm linkfunktioniert, bis es aufhört zu funktionieren: doppelte Abhängigkeiten, eine gehoistete Kopie, die gewinnt, und eine Auflösung, die sich anders verhält als die veröffentlichte. - Niemand wartet auf niemanden. Dein Service startet, ruft den auf, der noch nicht fertig hochgekommen ist, und der Fehler sieht aus wie ein Bug in deinem Code.
Was Aseptic macht
Aseptic erkennt einen Node-Service —oder ein Angular-Frontend— an seiner
package.json, startet ihn als nativen Prozess mit deinem eigenen Skript und
übergibt ihm die Konfiguration beim Start als Umgebungsvariablen. Die URLs zwischen den
Services werden dort umgeschrieben, keine .env deines Repositories muss sich
also ändern, und es gibt nichts, was man zurückzunehmen vergessen könnte.
Ein Szenario ist die Menge der Services eines Ablaufs, gestartet in Abhängigkeitsreihenfolge und auf die Health wartend, nicht auf den Prozess. Kollidierende Ports werden remappt, und der remappte Wert ist der, den die Aufrufer bekommen. Wenn der Ablauf Kafka, Redis oder PostgreSQL braucht, startet Aseptic sie in Docker und verwaltet sie — deine Services bleiben außerhalb von Docker, es sei denn, du willst sie containerisiert.
Jede Abhängigkeit wird dort aufgelöst, wo du es wählst: ein lokaler Service, den du offen hast, die gemeinsame Cloud-Umgebung oder ein Mock. Pro Abhängigkeit, und mitten am Nachmittag änderbar.
Lokale Pakete, ohne die Überraschungen von npm link
Wenn du gleichzeitig ein eigenes Paket und den Service änderst, der es benutzt, baut Aseptic
das Paket und verlinkt es in den node_modules des Verbrauchers, wo Node es
wirklich auflöst, und kann es beim Speichern neu bauen und neu verlinken. Es ändert die
package.json des Verbrauchers nicht, und das Aufheben der Verknüpfung macht nur
rückgängig, was es gesetzt hat. Derselbe Mechanismus deckt Maven, Gradle und Python ab, für
die Teams, deren Systeme nicht alle JavaScript sind.
Was es nicht tut
Es ersetzt weder deine Skripte noch deinen Bundler noch deinen Test-Runner: es ruft sie auf. Es führt keinen Kubernetes-Cluster aus, alles, was du auf dieser Ebene prüfen musst, gehört also zu einem anderen Werkzeug. Es braucht Docker für die gemeinsame Infrastruktur.
Es ist in öffentlicher Beta, erscheint für Windows, macOS und Linux und ist kostenlos für private Nutzung.
Neben den Alternativen
Wenn deine Services schon Images sind und du sie mit Manifesten deployst, die du pflegst, halten Tilt oder Skaffold die lokale Schleife in der Form der Produktion, zum Preis eines Builds bei jeder Änderung. Die Seite Docker-Compose-Alternativen deckt das ganze Feld ab.
Es gibt Entsprechungen dieser Seite für Spring Boot und für Quarkus.
Häufige Fragen
Warum reichen npm-Skripte mit mehreren Services nicht mehr?
Weil sie beim vierten nicht mehr tragen: ein Terminal pro Service, die Startreihenfolge im Kopf, und die URLs zwischen ihnen landen in Umgebungsvariablen, die auf jeder Maschine von Hand kopiert werden.
Brauche ich Docker-Images meiner Node-Services?
Nein. Aseptic startet sie als Prozesse mit ihrem eigenen Befehl; Docker ist für die gemeinsame Infrastruktur da.
Wie verlinke ich ein lokales Paket, ohne es auf npm zu veröffentlichen?
Aseptic baut es und verlinkt es in den node_modules des Verbrauchers und kann es bei Änderungen im laufenden Betrieb neu bauen und neu verlinken. Es ist umkehrbar: das Aufheben der Verknüpfung macht nur rückgängig, was es gesetzt hat.