
Auch Scripts brauchen Liebe!

Moritz
4. März 2020
Hinweis: Dieser Artikel wurde unter Zuhilfenahme von KI aus dem Englischen übersetzt. Hier geht's zum Originaltext.
Einer der einzigartigsten und attraktivsten Aspekte der modernen JavaScript-Entwicklung ist das Tooling, das sich darum rankt. Erinnerst du dich an die Zeiten, als deine Teammitglieder starke Meinungen zu Einrückungen hatten und sich gegenseitig für das Einchecken von "schlechtem" oder "hässlichem" Code kritisierten? Heutzutage kümmern sich ESLint und Prettier um dieses Problem, indem sie diese Meinungen in Konfigurationen festlegen und dich automatisch überprüfen, bevor du den Code überhaupt kompilieren kannst. Testen ist ein weiteres Beispiel für solches Tooling: Wir verwenden Jest für Unit-Tests, Cypress für E2E-Tests und alle möglichen Pretests, Checks und andere Linter. Und wir führen all das sowohl lokal als auch in der CI-Umgebung aus. All dieses Tooling ist schwer einzurichten und hat eine steile Lernkurve, aber sobald es funktioniert, leistet es großartige Arbeit bei der Aufrechterhaltung der Codequalität und Wartbarkeit, selbst in größeren Teams.
Der typische Einstiegspunkt zu diesen Tools ist der "scripts"-Abschnitt in der package.json, auch bekannt als "npm scripts" (obwohl sie auch mit yarn und anderen npm-Alternativen ausgeführt werden können). Sie bieten einfachen CLI-Zugriff auf alle Tools in deinem Projekt. Aber wenn es um die Wartbarkeit dieser Scripts geht, werden sie irgendwie vernachlässigt. Wenn du jemals in einer großen und ausgereiften JS-Codebasis gearbeitet hast, hast du es gesehen: Dutzende und Aberdutzende von Build-, Lint- und Test-Scripts, die sich manchmal gegenseitig mit pre*- oder post*-Präfixen aufrufen, Dinge sequenziell mit && ausführen und fast immer in einer scheinbar zufälligen Reihenfolge, die es schwer macht zu finden, wonach du suchst. Ein Albtraum.
Noch schlimmer ist, dass jeder Scripts-Abschnitt unterschiedliche - wenn überhaupt - Namens- und Aufrufkonventionen verwendet. Vielleicht startet npm run start einen prestart-Hook, der rm -rf ./dist ausführt, bevor Babel alles transpiliert und poststart einen Server startet? Vielleicht startet npm run start den lokalen Dev-Server plus irgendeine Art von Watcher? Vielleicht musst du das über start:development starten (oder war es start-develop?) - ohne direkt in die package.json zu schauen - wer weiß? Du kannst keine Kommentare in package.json hinzufügen und es gibt kaum jemals einen README-Abschnitt für die Scripts... oh, und was ist, wenn du ein neues Teammitglied einarbeitest, das darauf besteht, Windows zu verwenden? rm -rf ./dist wird unter Windows fehlschlagen.
test:lint oder test-lint, welches war es nochmal?
Können wir BITTE einen Weg finden, das auf konsistente Weise zu organisieren!? Können wir uns nicht auf ein paar Best Practices einigen!? Ich höre dich schreien. Nun, deine Freunde bei Peerigon haben genau das Richtige, um deine Schmerzen zu lindern.
Stand der package.json 2020
Dies ist gewissermaßen ein eigenes Blogpost-Thema, aber wir haben uns eingehend angesehen, wie Leute Package-Scripts verwenden. Wir haben die package.jsons der 1000 am häufigsten abhängigen npm-Module gecrawlt (es gibt bessere Metriken da draußen, wenn du die Daten hast - dies war einfach leicht zu crawlen) und ihre "scripts" untersucht. Einige häufige Muster haben sich herauskristallisiert:
1. Leute organisieren ihre Scripts in Namespaces
Du siehst viele build:* oder test:* Namen, was zwei Vorteile bietet: Es gruppiert Scripts sowohl visuell als auch alphabetisch (manche Leute halten alphabetische Reihenfolge durch die Zeilensortierungsfunktion ihrer Editoren ein).
2. : ist ein sehr gebräuchlicher Namespace-Separator
Es ist unklar, wer damit angefangen hat, aber es scheint der Favorit zu sein. Eine andere beliebte Option ist -.
3. Leute teilen komplexe Aufgaben in kleinere Schritte auf
Um Prozesse einfacher zu warten, ist es sehr üblich, ein komplexes Script in kleinere Teile aufzuteilen und sie dann sequenziell auszuführen. Meistens geschieht dies durch Verwendung von && — was auf *nix- und Windows-Systemen funktioniert. Eine weitere Best Practice, die du siehst, ist die Verwendung von npm-run-all. Die Verwendung von benutzerdefinierten Hooks (pre*/post*) ist weniger üblich, aber auch ein gültiger (wenn auch diskutabel unintuitiverer) Ansatz.
4. Manche Leute interessiert es einfach nicht
Es gibt alle möglichen Best Practices, die sich in diesen Erkenntnissen widerspiegeln, aber auch viele Projekte könnten etwas Hilfe mit ihren Scripts gebrauchen.
Nenn es keinen "Standard"

Bildunterschrift: Tim Myers auf Twitter
Als Technikfreaks neigen wir dazu, nach einem "Standard" zu greifen, wenn wir nicht sicher sind, wie man etwas "richtig" macht. Es gibt diesen berühmten xkcd-Comic über Standards, der ein Zeugnis für die Tendenz von Softwareentwicklern ist, neue Standards zu erfinden, wenn die alten nicht zu ihren Bedürfnissen passen.
In diesem Fall gab es keinen Standard. Die Benennung und Gestaltung von npm-Scripts ist unerforschtes Gebiet, und als Neuling bist du auf dich allein gestellt. Erfahrene JS-Entwickler haben durch Erfahrung eine Art, Dinge "richtig" zu machen, aber keine Möglichkeit zu erklären, warum oder wie.
Dennoch wollten wir davon absehen, ein kompliziertes und abstraktes technisches Standardpapier zu schreiben, das niemand lesen und verstehen kann. Wir möchten es so einfach wie möglich machen, die Scripts deines Projekts zu verbessern.
Deshalb haben wir...
scriptlint

... als CLI-Tool entwickelt - denke an einen Linter für deine Package-Scripts - mit konfigurierbaren Regeln und leicht konsumierbarer Dokumentation.
Hier ist ein Beispiel in einem webpack-basierten Frontend-Projekt, das scriptlint auf der Shell verwendet. Hier ist die Package-Datei:
Wenn du scriptlint in diesem Projekt ausführst, wirst du einige Warnungen sehen:
Dies sind die Warnungen aus den nicht-strikten/minimalen Regeln von scriptlint: Deine package.json muss Scripts namens dev, start und test enthalten, und letzteres kann nicht das Standard-Test-Script von npm init sein. So beheben wir diese Probleme:
- Da "Starten" des Projekts wahrscheinlich bedeuten würde, den Dev-Server zu starten, benennen wir start-dev in start um und erstellen einen Alias dev dafür. Andersherum wäre auch in Ordnung.
- Da wir noch keine Unit-Tests verwenden, definieren wir test als eine Kombination aus "der Code baut ohne Fehler" und "ESLint beschwert sich nicht" als nächstbeste Alternative. Wir können später Jest und/oder Cypress hinzufügen, wenn wir wollen, aber Bauen, Typ-Prüfung und Linting sollten Teil jeder test-Script-Kette sein.
So sieht das jetzt aus:
Führe scriptlint erneut aus, um zu prüfen:
Nachdem wir nun die minimalen Regeln hinter uns gebracht haben, verbessern wir das weiter, indem wir scriptlint --strict ausführen. Drei neue Warnungen tauchen auf:
Beginnen wir mit den ersten zwei Problemen, denn die sind am einfachsten zu beheben - durch Ausführen von scriptlint --strict --fix! Einige der Regeln können automatisch behoben werden, in diesem Fall wird scriptlint ...
- dem Script namens eslint den Fallback-Namespace other: voranstellen
- die Scripts alphabetisch sortieren
Da other:eslint kein großartiger Name ist, werden wir ihn manuell in test:lint umbenennen.
Das letzte verbleibende Problem ("Use of unix double ampersand (&&) in script 'test' is not allowed [...]") kann behoben werden, indem wir npm-run-all als devDependency installieren und test wie folgt umschreiben: run-s build test:lint. Eine schnelle Überprüfung durch Ausführen von scriptlint --strict --fix und schon ist es geschafft:
Ein perfekt "scriptlint-standard"-konformer Scripts-Abschnitt!
In diesem Beispiel haben wir etwa die Hälfte der verfügbaren Regeln in Aktion gesehen. Wenn du wissen möchtest, was scriptlint sonst noch für dich tun kann, schau auf unsere Github-Seite! Natürlich ist scriptlint Open Source (MIT-Lizenz), auf npm verfügbar, kommt mit JS-Modul-Unterstützung, TypeScript-Typdefinitionen, ist konfigurierbar und erweiterbar (benutzerdefinierte Regeln!). Es kann sowohl lokal in deinen Projekten als auch global in deiner Shell installiert werden. Hier ist unser Installationsleitfaden.
Wir hoffen, dass es deinem Team bei der Aufrechterhaltung der Script-Qualität hilft, und würden uns über dein Feedback freuen. Die Pflege des "Standards"/der scriptlint-Regeln sollte eine Community-Anstrengung sein!
Von Peerigon mit ❤️
Dank an Tanner Hoisington und Johannes Ewald.
npm scripts
Tooling
Linting
Code Quality Tools
Weitere Themen

Lea, 04.04.2025
Vue clever nutzen – Wiederverwendbarkeit für Einsteiger:innen
Vue
JavaScript
Reusability
DRY Principle
Components
Composables

Francesca, Ricarda, 02.04.2025
Die 10 häufigsten Fehler bei der Entwicklung digitaler Produkte – und wie du sie vermeidest
MVP development
UX/UI design
product vision
agile process
user engagement
product development

Judith, 31.03.2025