Node : démarrer plusieurs services en local
Node rend faciles les deux premiers services : npm start deux fois et vous
travaillez. Les ennuis arrivent avec le quatrième terminal, avec le deuxième service
qui veut lui aussi le port 3000, et avec le paquet que vous modifiez en même temps que
le service qui le consomme.
Ce qui casse en premier
- Les terminaux. Un par service, chacun avec son environnement, et sans mémoire de la combinaison qui marchait hier.
- Les ports. Tout arrive avec 3000 par défaut. Vous finissez avec un
.envpar développeur qui n'est jamais commité et jamais documenté. - Les URLs entre services. Chaque
fetchvers un autre service lit une variable, et en faire pointer trois vers l'environnement partagé signifie éditer des fichiers que vous ne devez pas commiter. - Le paquet local.
npm linkmarche jusqu'à ce qu'il cesse de marcher : dépendances dupliquées, une copie hoistée qui gagne et une résolution qui se comporte autrement que la version publiée. - Personne n'attend personne. Votre service démarre, appelle celui qui n'a pas fini de se lever, et l'erreur ressemble à un bug de votre code.
Ce que fait Aseptic
Aseptic détecte un service Node —ou un front Angular— par son
package.json, le démarre comme un processus natif avec votre propre script
et lui passe la configuration en variables d'environnement au démarrage. Les URLs entre
services sont réécrites là, donc aucun .env de votre dépôt n'a à changer et
il n'y a rien à penser à annuler.
Un scénario, c'est l'ensemble des services d'un flux, démarrés dans l'ordre des dépendances et en attendant la santé, pas le processus. Les ports qui entrent en collision sont remappés et c'est la valeur remappée que reçoivent ceux qui appellent. Si le flux a besoin de Kafka, Redis ou PostgreSQL, Aseptic les monte dans Docker et les gère — vos services restent hors de Docker, sauf si vous les voulez conteneurisés.
Chaque dépendance se résout là où vous le décidez : un service local que vous avez ouvert, l'environnement partagé du cloud ou un mock. Par dépendance, et modifiable en cours d'après-midi.
Des paquets locaux, sans les surprises de npm link
Si vous modifiez en même temps un de vos paquets et le service qui le consomme, Aseptic
construit le paquet et le lie dans le node_modules du consommateur, là où
Node le résout vraiment, et peut le reconstruire et le relier au fil de vos
enregistrements. Il ne modifie pas le package.json du consommateur, et
délier ne défait que ce qu'il avait posé. Le même mécanisme couvre Maven, Gradle et
Python pour les équipes dont les systèmes ne sont pas tous en JavaScript.
Ce qu'il ne fait pas
Il ne remplace ni vos scripts, ni votre bundler, ni votre lanceur de tests : il les appelle. Il n'exécute pas de cluster Kubernetes, donc tout ce que vous devez vérifier à ce niveau relève d'un autre outil. Il a besoin de Docker installé pour l'infrastructure commune.
Il est en bêta publique, publié pour Windows, macOS et Linux, et gratuit pour un usage personnel.
À côté des alternatives
Si vos services sont déjà des images et que vous les déployez avec des manifestes que vous maintenez, Tilt ou Skaffold gardent la boucle locale à la forme de la production, au prix d'un build à chaque changement. La page des alternatives à Docker Compose couvre tout le terrain.
Il existe des équivalents de cette page pour Spring Boot et pour Quarkus.
Questions fréquentes
Pourquoi les scripts npm ne suffisent-ils plus avec plusieurs services ?
Parce qu'ils ne tiennent plus au quatrième : il faut ouvrir un terminal par service, se souvenir de l'ordre de démarrage, et les URLs entre eux finissent dans des variables d'environnement recopiées à la main sur chaque machine.
Ai-je besoin d'images Docker de mes services Node ?
Non. Aseptic les démarre comme des processus avec leur propre commande ; Docker sert pour l'infrastructure commune.
Comment lier un paquet local sans le publier sur npm ?
Aseptic le construit et le lie dans le node_modules de celui qui le consomme, et peut le reconstruire et le relier à la volée quand il change. C'est réversible : délier ne défait que ce qu'il avait posé.