Das Symptom
Der Entwickler führt npm update aus, um alles auf den neuesten Stand zu bringen, und sieht danach in npm outdated immer noch ein Paket auf 1.9.4, obwohl 2.3.0 als latest veröffentlicht ist. Er wiederholt den Befehl, löscht node_modules, probiert npm update paketname, nichts passiert. Verdacht: npm-Cache, Registry-Spiegel, Proxy. Tatsächlich hat npm exakt das getan, was in der package.json steht, und dort steht ^1.9.4, also alles unter 2.0.
Die „Layer 8“-Wahrheit
Die npm-Dokumentation zu npm update sagt es im ersten Satz: „This command will update all the packages listed to the latest version (specified by the tag config), respecting the semver constraints of both your package and its dependencies (if they also require the same package).“ Der Befehl aktualisiert also, aber innerhalb der Grenzen, die das Projekt selbst gezogen hat. Für ^1.9.4 heißt das: alles bis unter 2.0.0, nie 2.x.
Das Beispiel in der Dokumentation führt es mit einer Tilde-Abhängigkeit vor: „Even though the latest tag points to 1.2.2, this version does not satisfy ~1.1.1, which is equivalent to >=1.1.1 <1.2.0. So the highest-sorting version that satisfies ~1.1.1 is used, which is 1.1.2.“ Der Tag latest ist eine Information, kein Befehl; was installiert wird, bestimmt der Bereich.
Außerdem ändert npm update die Bereichsangaben in der package.json standardmäßig nicht: „Note that by default npm update will not update the semver values of direct dependencies in your project package.json.“ Dafür braucht es den Schalter –save. Ein Sprung auf eine neue Hauptversion ist dagegen eine bewusste Entscheidung mit möglichen Brüchen und wird mit npm install paket@latest oder paket@2 gemacht, was den Bereich in der package.json neu setzt.
npm outdated zeigt die drei Spalten Current, Wanted und Latest genau deshalb getrennt: Wanted ist, was der Bereich erlaubt, Latest, was es gibt. Wer die beiden Spalten als Widerspruch liest, sucht den Fehler im Werkzeug. Wer sie als zwei verschiedene Fragen liest, sieht, dass npm beide richtig beantwortet hat, und dass die dritte Frage, ob das Projekt die neue Hauptversion verträgt, nicht npm beantworten kann, sondern nur ein Blick ins Changelog und ein Testlauf.
Der Reflex, bei einer unerwarteten Versionsnummer den Cache zu leeren oder die Registry zu verdächtigen, kommt daher, dass npm selten erklärt, warum es etwas nicht tut. Es tut es einfach nicht. Die Erklärung steht in der package.json, die man selbst geschrieben oder von einem Generator übernommen hat, und sie lautet in einem Zeichen: das Dach vor der Version. Wer es liest, weiß, was npm update darf, und wer es ändert, weiß, dass er es war.