Das Symptom
Du hebst Node von einer Hauptversion auf die nächste – ein Kommando, eine
Minute – und die Anwendung startet nicht mehr. Der Stacktrace zeigt keine Zeile
deines Codes, sondern das Laden einer .node-Datei tief in node_modules.
Irgendein Paket, das du nie bewusst installiert hast, sondern das als
Abhängigkeit einer Abhängigkeit mitkam.
Der Quelltext hat sich nicht geändert. Das Lockfile hat sich nicht geändert.
Geändert hat sich nur die Zahl hinter node --version.
Die „Layer 8“-Wahrheit
Native Addons sind kein JavaScript. Es sind kompilierte Binärdateien, die direkt gegen die C++-Innereien von Node und gegen V8 gebaut wurden – und die Node-Doku macht daraus kein Geheimnis: „The V8 API can, and has, changed dramatically from one V8 release to the next (and one major Node.js release to the next). With each change, addons may need to be updated and recompiled in order to continue functioning.“ Übersetzt: Diese Binärdatei war nie für die Node-Version gebaut, die du gerade installiert hast, und sie tut auch nicht so als ob.
Das Unangenehme daran ist die Verteilung der Schuld. Du hast nichts falsch gemacht, das Paket auch nicht – die Kombination passt nur nicht. Und weil das Paket typischerweise drei Ebenen tief in der Abhängigkeitskette sitzt, hat niemand in deinem Team es je bewusst ausgewählt. Ein Node-Update ist deshalb nie nur ein Node-Update, sondern immer auch ein Test darauf, ob alle kompilierten Anteile deines Baums für die neue Version verfügbar sind.
Dass das überhaupt noch ein Alltagsproblem ist, ist ein Erbe. Node-API ist
ausdrücklich als Ausweg gebaut: „This API will be Application Binary Interface
(ABI) stable across versions of Node.js. It is intended to insulate addons from
changes in the underlying JavaScript engine and allow modules compiled for one
major version to run on later major versions of Node.js without recompilation.“
Wer Node-API benutzt, hat dieses Problem nicht mehr. Wer weiter direkt gegen
v8.h baut, hat es bei jeder Hauptversion wieder – und du erbst es mit.