NPM ist mit Proxy sehr langsam

Mir ist unter Windows aufgefallen, dass sich npm seltsam langsam verhält, wenn man es mit Prozessüberwachung ausführt und systemweit ein Proxy konfiguriert ist.
Folgendes Beispiel soll dies veranschaulichen:

PS C:\Users\kirk> Measure-Command {npm -v}

Days              : 0
Hours             : 0
Minutes           : 1
Seconds           : 9
Milliseconds      : 88
Ticks             : 690884385
TotalDays         : 0,000799634704861111
TotalHours        : 0,0191912329166667
TotalMinutes      : 1,151473975
TotalSeconds      : 69,0884385
TotalMilliseconds : 69088,4385

Dem geschulten Auge fällt auf: 69 Sekunden Laufzeit?!

Was passiert hier?

Startet man eine Aktion mit npm wird die gewünschte Aktion flink ausgeführt. Aber um ganz sicher zu gehen, dass es sich auch wirklich um die aktuellste Version von npm handelt wird ein weiterer Prozess gestartet welcher im Internet nachschaut.
Findet npm keine neue Version wird vermerkt wann zuletzt nachgeschaut wurde und der Prozess beendet sich.
Das passiert in der Regel so schnell, dass es keinem wirklich auffallen sollte.

Soweit zur Theorie.

Eine eigentlich nützlich erscheinende Funktion stellt sich unter bestimmten Umständen als herausragende "Effektivitätsbremse 2.0" dar.
Hat man sein System vorbildlich auf den Einsatz mit einem Proxy vorbereitet und führt Measure-Command {npm -v} in einer PowerShell aus wundert man sich über anfangs aufgeführtes Ergebnis.

Schaut man genauer hin stellt man fest, dass dieser Aufruf 2 nodejs Prozesse startet. Diese bleiben dann in meinem Fall 69 Sekunden da und tuen nichts.
Noch etwas genauer hingeschaut erkennt man, dass einer dieser Prozesse mit folgendem Aufruf gestartet wurde:

"C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\node_modules\update-notifier\check.js" "{\"pkg\":{\"name\":\"npm\",\"version\":\"5.6.0\"}}"

Ok, schauen wir noch genauer hin:
update-notifier ist ein npm Paket welches eine Abhängigkeit auf latest-version hat. Jenes wiederum ist abhängig von package-json und besitzt seinerseits eine Abhängigkeit auf got.

Ein klein wenig genauer hingeschaut und einem fällt ein Issue ins Auge welches der Ersatz für einen weiteres Issue ist.
Aus diesem möchte ich hier gern den Entwickler zitieren: "I don't really care about proxy support"

Zwischenergebnis

npm kann für den Umgang mit Proxys konfiguriert werden aber der Check welcher bei jedem Aufruf ausgeführt wird ignoriert die Einstellungen einfach! Dies hat zur Folge, dass der Request zur Versionsabfrage im Nirvana verendet und kein Ergebnis zurückgeben kann. Wenn der Request in das Timeout rennt, stirbt der Prozess und tut nichts weiter.
Daraus folgt, dass beim nächsten Aufruf von npm der selbe Spaß von vorn los geht.

Was ist jetzt daran das Problem?

Ist der npm - Aufruf in ein System eingebettet welches die gestarteten Prozesse überwacht beginnt der Hamster schnell zu humpeln. Als Beispiel sei hier ein msbuild Skript oder die Tasks im TFS genannt.
Der überwachende Prozess wartet natürlich vorbildlich bis alle Kinder des aufgerufenen Programms beendet sind. Dass da dieser sinnlose "Ich warte mal auf eine Versionsinformation aus dem Internet" Prozess dabei ist kann der Aufrufer nicht wissen.

Lösungsvorschläge?

Die sinnvollste Lösung ist aus meiner Sicht einen Konfigurationsparameter für npm zu haben welcher die Versionsüberprüfung komplett abschaltet.

Gibt es nicht! Nächster!

update-notifier prüft einen Parameter --no-update-notifier.
Dieser wird von npm allerdings nicht weitergereicht. Nächster!

update-notifier prüft eine Umgebungsvariable NO_UPDATE_NOTIFIER. Wenn diese den Wert 1 hat wird die Prüfung übersprungen. Treffer!

Lösung

Auf Maschinen welche nicht auf die Prüfung angewiesen sind und welche Aufgaben mit npm ausführen sollen ist es ratsam die Umgebungsvariable NO_UPDATE_NOTIFIER auf den Wert 1 zu setzen.

Ergebnis

PS C:\Agents> Measure-Command {npm -v}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 785
Ticks             : 17855814
TotalDays         : 2,06664513888889E-05
TotalHours        : 0,000495994833333333
TotalMinutes      : 0,02975969
TotalSeconds      : 1,7855814
TotalMilliseconds : 1785,5814

Schon irgendwie besser.

Anmerkungen

Das hier beschriebene Verhalten ist bereits in einem Issue im npm Projekt erfasst.

Ich konnte leider nicht prüfen ob auch andere Systeme als Windows davon betroffen sind.

Das Setzen der Umgebungsvariable NO_UPDATE_NOTIFIER hat zur Folge, dass das für alle Pakete deaktiviert wird welche update-notifier verwenden.