Mein Homeverzeichnis liegt auf einem Dateisystem, das regelmäßig
Snapshots erstellt. Damit ich schön viele Snapshots ganz lange
aufheben kann, ohne allzuviel Platz zu verschwenden, habe ich volatile
und transiente Daten (also im wesentlichen irgendwelche Caches) auf
ein anderes Dateisystem verschoben und passende Symlinks gesetzt.
Begründung: Die Cache-Inhalte sind (mir) nicht wichtig und können
jederzeit neu erstellt werden, also muss ich damit nicht die Snapshots
aufblähen. Teilweise werden die auch echt groß. Beispiele sind
~/.cache
oder die Caches von Firefox, Maven und Gradle.
Nun bastele ich aktuell mit TypeScript rum und habe dort in jedem
Projekt ein Unterverzeichnis node_modules
mit Daten, die sich a) aus
dem Internet wiederherstellen lassen, b) laufend ändern (Paket-Updates
all over) und c) nicht gerade klein sind (ein leeres Angular-Projekt
hat 300MB Abhängigkeiten). Top Kandidaten für die Auslagerung auf das
Cache-Dateisystem ohne Snapshots.
Also wird node_modules
ein Symlink auf
$CACHE-DIR/$PROJECTNAME-node_modules/
und alles ist gut – bis zum
zweiten Aufruf von npm install
. Dann geht nämlich alles kaputt
und es gibt lustige Compilerfehler, weil die ganzen Pakete plötzlich
nicht gefunden werden. WAT?
Ja, also, das ist so: Symlinks funktionierten mal. Mit npm 2.0.
Bis 2015. Denn dann kam npm 3.0 heraus und seitdem funktioniert das
Symlinken von node_modules
halt nicht mehr. WAT?
Hier ist der Bug dazu. Ganz viele Leute beschreiben, warum sie mit
Symlinks arbeiten (müssen), der Bug wird bis ins letzte Jahr hinein
(also fünf Jahre nach seiner Erfassung) von anderen Bugs aus anderen
Projekten heraus verlinkt und was macht npm? Hat ihn 2016
geschlossen, wie es aussieht ohne tatsächlichen Fix. Weitere
Kommentare zu dem vor sich hin schwärenden Problem? Fehlanzeige.
WAT?
Rettung verspricht letztendlich dieser Kommentar aus 2016: Das Problem
tritt nur auf, wenn Quelle und Ziel des Symlinks unterschiedliche
Namen haben. WAT?
Ich habe das ausprobiert: Es ist tatsächlich so. Wenn ich nicht auf
$CACHE-DIR/$PROJECTNAME-node_modules/
symlinke, sondern stattdessen
$CACHE-DIR/$PROJECTNAME/node_modules/
(also eine Ebene tiefer ein
Verzeichnis mit Namen node_modules
) als Ziel des Symlinks nehme,
funktioniert wieder alles. Dank an Herrn woohoou.
Warum sich keiner um den Fehler kümmert sei mal dahingestellt, aber
wie kann es überhaupt zu so etwas komischem kommen? Das einzige, was
mir dazu einfällt, ist folgendes: Man folgt dem Symlink und
durchstöbert das Node-Repository, auf das der Link zeigt. Zu den
einzelnen Node-Paketen dort holt man sich den absoluten Pfad (also
den, der das Symlink-Ziel enthält). Um dann herauszufinden, wo in
diesem Pfad das Node-Repository anfängt, sucht man stumpf mit
indexOf()
nach dem Namen, den der ursprüngliche Symlink hatte (also
bei mir node_modules
). WAT?
Ich bin versucht, den Symlink spaßeshalber mal auf eine
Verzeichnishierarchie zeigen zu lassen, in der node_modules
mehrfach
vorkommt. Aber kaputter als kaputt geht nicht und kaputt kriege ich auch
ohne besondere Anstrengungen hin.
Mir war dieses schnellebige, zerfledderte, auf wackeligen
Abhängigkeiten basierende Ökosystem schon immer suspekt und diese neue
Erfahrung hat mich jetzt nicht vom Gegenteil überzeugt.