JavaScript Gom Jabbar
(frantic.im)- Ein JavaScript-Entwickler mit 10 Jahren Erfahrung nimmt das Lesen von
package.jsonals Prüfung des Schmerzes und zeigt, wie viel angesammelte Komplexität des Ökosystems in einer einzigen Konfigurationsdatei steckt - Felder wie
main,browserundtype: modulerufen alte Migrationswunden rund um Isomorphic JavaScript, Browser-Bundles sowie den Übergang von CommonJS zu ESM in Erinnerung - In
scripts,dependenciesunddevDependenciesverknüpfen sich alte Tools und Probleme der Paketverwaltung wie Lint-Varianten,watchman, gulp,left-pad, moment.js undresolutions eslint,postcss,jestsowie Build- und Test-Tools erhöhen durch strenge Regeln, plattformspezifische Installationsfehler und die schwierige Konfiguration von ESM und TypeScript die Kosten für die Pflege der Entwicklungsumgebung- Dass man trotz Node-
enginesnicht zu Bun oder Deno wechselt, liegt an der Überzeugung, dass der Schmerz nicht verschwindet, sondern noch größer würde; der Entwickler schließt die Datei und überlebt erst einmal
Die Prüfung, package.json zu lesen
- Die Geschichte beginnt damit, dass ein Entwickler, der seit 10 Jahren JavaScript nutzt, vor dem Computer sitzt, die Datei
package.jsonöffnet und sie bis zum Ende lesen muss - Diese Datei ist nicht einfach nur eine Konfigurationsdatei, sondern ein Objekt, das alle Erinnerungen und Schmerzen aus dem JavaScript-Ökosystem auf einmal wachruft
versionhat noch immer nicht1.0erreicht, und SemVer bleibt als unangenehme Erinnerung daran, dass man schon vor langer Zeit gelernt hat, es zu ignorierennamezeigt die Situation, dass man den gewünschten Namen nicht verwenden kann, weil ihn schon vor 7 Jahren jemand durch ein Paket belegt hat, das seitdem nicht mehr aktualisiert wurde
Alte Wunden von Modulen und Bundling
- Dass die Felder
mainundbrowsergemeinsam vorhanden sind, legt Spuren von Isomorphic JavaScript offen - Die Erinnerung daran, in einem Browser-Bundle per
requiredas Modulfsladen zu wollen, und an die Hacks, die nötig waren, damit es funktioniert, bleibt als unangenehme Erfahrung zurück type: moduleist mit der Migration vonrequirezuimportverbunden- Der Versuch, CommonJS- und ESM-Module gegenseitig zu importieren, ist als großer Schmerz in Erinnerung geblieben
Das Durcheinander aus Scripts und Abhängigkeiten
scriptsist das Zentrum eines heißen, schmerzhaften Durcheinanders- Es gibt Varianten wie
lint,lintall,lintfastundlintdiff - Parallele Ausführung, unklare Argumente und doppelt escapte Argumente im JSON-Format tauchen auf
- Auch nach dem Wechsel zu yarn und pnpm rufen einige Unterbefehle weiterhin npm auf
- Es gibt Varianten wie
- Einige Scripts verwenden noch immer
watchman- Man muss sich daran erinnern, dass man es nicht verwenden sollte, weil es keine Symlinks unterstützt
- Das zugehörige Issue ist seit 2015 offen
- Auch gulp-basierte Scripts sind noch vorhanden; man würde sie gern durch etwas Moderneres ersetzen, aber niemand hat den Mut dazu
Das Trauma, das die Paketliste auslöst
- In
dependenciesstehen sehr viele Pakete, und jedes Paket belebt seine eigenen Trauma-Erinnerungen wieder left-padist ein kleines Paket, bleibt aber als legendäres Paket in Erinnerung, das „das ganze Internet kaputtgemacht“ hat- Jedes Mal, wenn die Abhängigkeitsliste geändert wird, geben einige Pakete lange Spendenaufrufe oder Warnungen vor Breaking Changes in der Konsole aus
- Der Entwickler befindet sich in einem Zustand, in dem er nur noch hofft, dass kein bösartiges Paket Geheimnisse stiehlt oder den Computer zerstört
- moment.js bleibt als Bibliothek mit einer guten API in Erinnerung, doch das Internet kam zu dem Urteil, dass sie zu mutable, zu groß ist und kein Treeshaking unterstützt; nun steht die Migration zu date-fns an
- Die Paketversionen liegen deutlich hinter dem heutigen Stand zurück und müssten aktualisiert werden, doch aufgrund früherer Upgrade-Erfahrungen ist großer Schmerz zu erwarten
resolutionsbleibt als weiterer Schmerz zurück, den man gewählt hat, um Paket-Upgrades zu vermeiden
Eine weitere Komplexität durch Entwicklungswerkzeuge
- Beim Blick auf
devDependenciesfällt es schwer, sich an die Zeit zu erinnern, in der man nur non-dev dependencies brauchte - Die
eslint-Konfiguration ist so streng geworden, dass schon bei kleinen Fehlern rote Unterstreichungen erscheinen und CI Lint-Probleme wie das Ende der Welt behandelt- Junior Engineers im Team gibt sie ein falsches Gefühl von Sicherheit
- Es gab mehrfach Streit darüber, welche Regeln aktiviert werden sollen
- Der Schmerz wächst mit der Zahl der
eslint-ignore-Einträge überall in der Codebase
postcsswird nicht direkt verwendet, existiert aber als Paket, das von einer Abhängigkeit einer Abhängigkeit verlangt wird- Bei jedem Versuch, auf einer neuen Plattform
npm installauszuführen, verursacht es unklare C++-Kompilierfehler
- Bei jedem Versuch, auf einer neuen Plattform
jestbegann als schneller Test-Runner, ist inzwischen aber groß und schwer geworden und hängt von einigen Babel-Paketen ab- Der Rest der Anwendung wird mit einer Kombination aus esbuild und swc transpiliert
- Es korrekt für ESM und TypeScript einzurichten, ist schwierig wie ein „PhD-Wissenschaftsprojekt“
- In der Codebase sind viele Tools und Parser beteiligt, darunter TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup und terser
- In
enginesistnodeangegeben, und selbst wenn man zu Bun oder Deno wechseln würde, geht man davon aus, dass der Schmerz nicht aufhört, sondern schlimmer wird - Nachdem die letzte schließende geschweifte Klammer gelesen ist, schließt er den Tab, holt Luft und überlebt erst einmal mit intakten Händen und intaktem Gehirn
1 Kommentare
Hacker-News-Kommentare
Ziemlich lustig. Ich habe etwa 18 Jahre lang JavaScript geschrieben und vor ungefähr 3 Jahren damit aufgehört, und die meisten Sorgenpunkte auf dieser Liste stammen aus den letzten 10 Jahren.
Besonders auffällig ist, dass Polyfills fehlen, die 2013 zwingend dabei gewesen wären. Was für JavaScript-Albträume aus dem Jahr 2013 sind heute sonst fast verschwunden? Natürlich wurden sie durch diese lustige Liste ersetzt.
Mein Lieblingsabschnitt war der, in dem man die funktionierenden Tools und Parser in der Codebasis zu zählen beginnt und dann auf TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup und terser kommt und der Schmerz so groß wird, dass man gar nicht mehr wissen will, was man noch vergessen hat.
undefined,with, per Closure nachgebildete private Felder, veränderte Prototypen, implizite globale Variablen,this, das sich je nach Aufrufstelle verändert, automatische Typumwandlung bei Vergleichen …Ja, so sind mehr als 10 Jahre JavaScript vergangen.
SomeFunction.prototypegebaut wurden.Das wurde dann in eine sofort ausgeführte anonyme Funktion gepackt und als Objekt zurückgegeben, sodass man
new SomeFunction()oderSomeFunction.actualFunction()aufrufen konnte, als wäreSomeFunctioneine Klasse. Dazu kam noch, dass es keine Arrow Functions gab, weshalb man zur Bindung von Events an den Scope gleichFunction.prototypeselbst veränderte und.apply()benutzte, oder in eine endlose.bind(this)-Hölle für jeden Event-Callback geriet.Heute hatte ich wieder das Pech, eine Testaufgabe für eine Firma zu schreiben, die immer noch pures JavaScript ohne Promises oder Deklarationsdateien verwendet, und es fühlte sich an, als wäre ich zurück im Jahr 2012, als ich Node zum ersten Mal begegnet bin. Die Vorgabe, JavaScript zu verwenden, habe ich zwar mit JSDoc umgangen, aber es war viel schlimmer, als ich es in Erinnerung hatte.
Jedes Mal, wenn ich ein neues JavaScript- oder genauer gesagt TypeScript-Projekt starte, durchlaufe ich immer denselben Ablauf.
Meist ist es Frontend, also entscheide ich mich für React, obwohl ich auch mal Svelte ausprobieren möchte. Beim Bundler waren es früher create-react-app oder Webpack-Wrapper, heute ist Vite wegen der geringen Konfiguration und der Unterstützung aller wichtigen Frameworks die beste Wahl.
Dann installiere und konfiguriere ich den TypeScript-Compiler, meist per Copy-paste aus einem Template. Als Ziel setze ich aktuelles stabiles JavaScript und ESM-Module, richte eslint und prettier passend ein und füge Plugins für TypeScript und React hinzu. Außerdem baue ich Hooks ein, die vor Commits Prettier und eslint ausführen.
Ich installiere auch IDE-Erweiterungen und lege ein
.devcontaineroder eine Liste empfohlener Extensions an. Für den Stil selbst interessiere ich mich nicht, wichtig sind mir Code-Konsistenz und das Erkennen von Fehlern, deshalb nutze ich bei eslint meist bestehende Konfigurationen.Danach richte ich Unit-Tests wie jest oder vitest ein, und schon kommen wieder TypeScript-bezogene Einstellungen und eslint-Regeln dazu. Als CSS-Framework mag ich tailwind, also installiere ich auch styled-components und twin.macro, damit es gut mit React zusammenspielt, dazu noch ein Google-Fonts-Plugin oder eine Font-Bibliothek.
Erst nach etwa einem Tag kann ich überhaupt mit dem Programmieren anfangen. Warum ist das so viel Arbeit? So viele Leute nutzen Kombinationen wie Vite + TypeScript + React/Vue/Svelte + eslint/prettier + tailwind/bootstrap + jest/vitest — warum gibt es keine Zero-Config-Bibliothek, die für 90 % der Anwendungsfälle sofort passt?
Selbst wenn ich die Toolchain irgendwie zum Laufen gebracht habe, hatte ich nie das Gefühl, sie unter Kontrolle zu haben; es wirkte, als würde alles schon bei der kleinsten Erschütterung zusammenbrechen, und als könnte ich es dann auch nicht reparieren.
In letzter Zeit habe ich beschlossen, den Großteil dieses JavaScript-Stacks als Hindernis für das zu sehen, was ich eigentlich machen will, und habe wieder eine serverseitig gerenderte App auf Basis von Flask und Jinja2 gebaut. Sie ist nicht modern-glänzend und ohne CSS momentan ziemlich hässlich, aber mir wurde geraten, einfach mit reinem modernem CSS weiterzumachen. Trotzdem ist es erstaunlich, wie schnell man in diesem Stack Features bauen kann.
package.json. Zugegeben, ich mache eigentlich nur Backend, aber könnte man sich nicht auch fürs Frontend so ein persönliches Template bauen?npm create?Wenn man
npm create vueausführt, bekommt man eine ziemlich gute, funktionierende Vue-Konfiguration, bei der der Großteil schon eingerichtet ist. Ich stimme zu, dass es viel Boilerplate und allerlei Spielereien gibt, aber die Apps, die wir heute fürs Web bauen, sind auch viel größer als früher. Man könnte JavaScript mit ESModules auch ganz ohne Tooling verwenden, aber meist tut man das nicht, weil diese Tools tatsächlich etwas leisten. Es ist nicht die eleganteste Lösung, aber es funktioniert immerhin.Wenn man ein neues Projekt startet, klont man es einfach und ändert nur ein paar Namen, dann ist alles bereit.
Das ist wieder so ein Fall, in dem Leute JavaScript sagen, aber eigentlich „zusammengewürfelter Kram aus dem Node-Ökosystem“ meinen.
Es fängt schon damit an, dass man eine
package.json-Datei öffnen und lesen soll, und danach bleibt es die ganze Zeit in dieser Spur. Von den erwähnten Dingen hat fast nichts wirklich mit JavaScript selbst zu tun.Es stimmt schon, dass JavaScript und NodeJS nicht dasselbe sind, aber die meisten werden wohl verstanden haben, was der Autor gemeint hat. Präziser wäre besser gewesen, aber komplett falsch ist es auch nicht.
package.jsonverwendet. Bis ECMA einen Paketmanager oder Bundler in die offizielle Spezifikation aufnimmt, istpackage.jsonfaktisch Teil von JavaScript.Ich mag den scherzhaften Ton. Nachdem einem Haut und Nervenenden ein paar Schichten tief weggebrannt wurden, ist es hilfreich, sich solche Schmerzpunkte noch einmal ins Gedächtnis zu rufen.
Anders gesagt: Man kann einem motivierten Junior-Entwickler ein neues MacBook geben und ihn ins kalte Wasser werfen, und innerhalb eines Tages ist er produktiv. Er muss nichts über Container, .NET, nginx oder 100 oft benutzte Kommandozeilen-Tools wissen, und wenn etwas schiefläuft, sucht man einfach danach.
Obwohl man weiß, dass man in ein paar Tagen ein ganzes Schiff bauen könnte, wenn man es nur direkt mit den Händen anfassen dürfte, kämpft man stattdessen mit Schichten unnötiger Komplexität, während man mit dem bereitgestellten schäbigen Werkzeug ein Schiff in der Flasche repariert. Genau so fühlt es sich an, wenn man bei einem privaten Projekt mit nur JavaScript, HTML und CSS schnell vorankommt und dann in moderne Frontend-Arbeit geworfen wird.
Dass das Monate dauert und ein Teil des Problems genau in diesem Framework-Übermaß liegt und es am nächsten Tag schon veraltet ist, wissen sie in ihrer Naivität nicht.
„Ich habe die Anleitung befolgt, und dann hieß es, grunt sei nicht installiert. Ich bin inzwischen ein alter Mann und wusste nicht so genau, was grunt ist, und auch meine grunt-Datei stimmte irgendwie nicht. Also habe ich ein bisschen gesucht und herausgefunden, was grunt ist. Grunt ist … ehrlich gesagt weiß ich immer noch nicht genau, was das ist.“
--Joe Armstrong, https://www.youtube.com/watch?v=lKXe3HUG2l4
Vor ein paar Tagen habe ich
gem install wayback_machine_downloaderausgeführt. Ich mochte Ruby nie genug, um wirklich in dieses Ökosystem einzusteigen, aber von außen betrachtet scheint dieses Ökosystem erstaunlich stabil gepflegt worden zu sein. gem ist immer noch das Werkzeug, das man verwendet, und Rails gibt es immer noch.Ich warte auf ein neues Projekt, das komplexes Frontend braucht und mehr als 0 bis 30 Zeilen JavaScript rechtfertigt. Dann wäre ich mit HTMX vermutlich glücklicher als mit dem derzeit beliebtesten riesigen Framework.
Das ist kein Artikel über JavaScript, sondern über npm.
Wegen genau so eines Durcheinanders hasse ich npm und meide es, wo ich kann. Privat nutze ich Deno, und bei der Arbeit verwenden wir etwas Monorepo-basiertes, Bazel-ähnliches, das dafür sorgt, dass wir npm nicht brauchen.
Trotzdem finde ich JavaScript/TypeScript angenehme Sprachen zum Programmieren und greife bei fast allem zuerst dazu. Es ist traurig, wenn Leute sagen „JavaScript ist Mist“, obwohl sie eigentlich meinen, dass es Mist ist, mit npm eine React-App zu bauen. Modernes JavaScript-/TypeScript-Coding macht wirklich Spaß.
Ich habe das Gefühl, JavaScript und sein Ökosystem haben uns allen PTSD hinterlassen, sodass wir die Komik dieses Textes gar nicht mehr genießen können.
Es gibt viel zu viele „ernste“ Diskussionen über einen lustigen Text. Man kann ihn gern nach Belieben sezieren, aber es wäre gut, im Kopf zu behalten, dass die eigentliche Absicht Humor ist.
Ehrlich gesagt war Node das erste Ökosystem, mit dem ich angefangen habe, und die Dinge, die ich später gelernt habe, hatten jeweils ebenfalls genug irre Probleme.
Haskell war auf mehreren Maschinen extrem schwer zu benutzen, selbst 2019 war die Installation auf MacOS schmerzhaft, und auch die Pflege des Ökosystems war schwierig. Makros und Erweiterungen sind stark verwirrend, und die Abwärtskompatibilität der Sprache ist ebenfalls nicht gut. Dagegen kann man bei JavaScript von 2010 normalerweise erwarten, dass es 2023 noch funktioniert.
Schon das saubere Aufsetzen von Docker-Images oder Umgebungen wie codespace/gitpod ist schwierig, und auch die von GitHub bereitgestellten Standard-Images sind nicht besonders gut und haben Probleme.
C ist auf den meisten Plattformen größtenteils okay, aber die Sprache selbst ist ehrlich gesagt komplex, und man braucht riesiges Wissen über das gesamte System. Das führt leicht zu wenig portablem Code, der für die meisten allgemeinen Programmierzwecke ungeeignet ist.
Ich könnte noch weitermachen, aber wer mehrere Sprachen benutzt hat, weiß, dass jedes Ökosystem diverse Schwächen hat und wir alle weiter leiden. Bei PHP habe ich ein Projektsetup noch nie in wenigen Tagen abgeschlossen, und Elm ist zwar weniger schmerzhaft, hat aber seine eigenen Probleme mit seinem wohlwollenden Diktator-Modell und der Entwicklungsgeschwindigkeit.
Ich bin ein polyglotter Entwickler, der sich mit mehreren Programmierparadigmen und Sprachen ebenso wohlfühlt wie mit Frontend und Backend
Jedes Mal, wenn ich sehe, dass eine
package.jsonlänger als 20 Zeilen ist, reagiere ich fast genau sopackage.jsonist über 200 Zeilen langIch spreche laut vor mich hin, als wollte ich einen Dämon abwehren. „Du darfst keine Angst haben. Angst tötet den Verstand. Angst ist der kleine Tod, der völlige Vernichtung bringt. Ich werde mich meiner Angst stellen. Ich werde zulassen, dass sie über mich hinweggeht. Und wenn sie vorüber ist, werde ich mit dem inneren Auge ihren Weg betrachten. Wo die Angst vergangen ist, wird nichts zurückbleiben. Nur ich werde bleiben.“
weint
hackernewsersnie benutzt, daher weiß ich nicht, ob das normales Verhalten istEin altmodischer JavaScript-Entwickler liest den Artikel und leidet unter PTSD und Flashbacks
Du darfst keine Angst haben. Angst tötet den Verstand. Angst ist der kleine Tod, der völlige Vernichtung bringt
Ich werde mich meiner Angst stellen. Ich werde zulassen, dass sie über mich hinweggeht. Und wenn sie vorüber ist, werde ich mit dem inneren Auge ihren Weg betrachten
Wo die Angst vergangen ist, wird nichts zurückbleiben. Nur ich werde bleiben
Er beendet die Lektüre des Artikels und merkt, dass er überlebt hat, ist aber bereits schweißgebadet