mitmario.dev

Die package.json

Node.js Sandbox 4 Min Lesezeit 3 BeispieleLektion 1 von 7

Bis hierhin waren deine Dateien einzelne Skripte. Ab jetzt sind sie ein Projekt, und ein Projekt hat eine Datei, die es beschreibt.

npm init -y legt sie an. Das -y heißt: keine Rückfragen, nimm die Vorgaben. Heraus kommt eine package.json mit einer Handvoll Feldern, von denen die meisten dich erst einmal nicht interessieren müssen.

Die Felder, die wirklich etwas tun

Eine package.json, die etwas bewirkt
import { readFile } from "node:fs/promises";

const eintraege = JSON.parse(await readFile("daten.json", "utf8"));

console.log(`${eintraege.length} Einträge geladen`);

Das ist ein vollständiges kleines Projekt: eine Beschreibung, eine Datenliste und ein Programm, das sie liest. Starte es, und im Terminal steht 4 Einträge geladen. Interessant sind hier aber nicht die vier Einträge, sondern die Felder daneben.

type ist der wichtigste Eintrag für diesen Kurs. Steht dort "module", behandelt Node jede .js-Datei im Projekt als ES-Modul. Genau das ist der Schalter aus Lektion 2.2, und ab hier benutzen wir ihn: Die Dateien heißen ab diesem Abschnitt .js und nicht mehr .mjs.

main sagt, welche Datei gemeint ist, wenn jemand dein Paket einbindet, ohne eine Datei zu nennen. Für ein Programm, das du selbst startest, spielt es keine Rolle.

scripts ist eine Liste von Befehlen unter einem Namen. Dazu gleich mehr, das ist der zweite wichtige Eintrag.

dependencies und devDependencies führen die Pakete, die dein Projekt braucht. Sie kommen in Lektion 5.2 dran und werden meistens nicht von Hand geschrieben.

engines hält fest, mit welchen Node-Versionen dein Projekt laufen soll. npm warnt, wenn es nicht passt, und viele Hosting-Anbieter lesen das Feld und richten sich danach.

private ist ein Wächter. Steht dort true, weigert sich npm publish, das Projekt zu veröffentlichen. Das klingt nach einem Detail, bis es jemandem zum ersten Mal passiert. In jedes Projekt, das nicht veröffentlicht werden soll, gehört "private": true, und das sind fast alle.

name, version, description, author, license und keywords sind dagegen reine Beschreibung. Wichtig werden sie, wenn du wirklich veröffentlichst.

Warum scripts mehr ist als eine Abkürzung

Was npm start daraus macht
{
  "name": "einkaufsliste",
  "version": "1.0.0",
  "type": "module",
  "private": true,
  "scripts": {
    "start": "node index.js"
  }
}

npm macht dabei nicht viel: Es zeigt den Namen des Projekts, zeigt den Befehl, den es gleich ausführt, und führt ihn dann aus. Was dein Programm schreibt, kommt darunter.

Der eigentliche Gewinn ist aber nicht das Tippen. Es ist die Verabredung.

npm start und npm test heißen in jedem Node-Projekt der Welt gleich. Wer dein Projekt zum ersten Mal in die Hand nimmt, probiert diese beiden, und wenn sie funktionieren, ist er drin. Er muss nicht in der README nachlesen, ob das Ding nun mit node server.js, node src/main.js oder node --env-file=.env app.js startet.

Dasselbe gilt für Werkzeuge. Ein Hosting-Anbieter, der dein Projekt deployt, ruft npm start auf. Eine CI-Pipeline ruft npm test auf. Beide fragen nicht nach.

Ein eigener Befehl mit npm run
{
  "name": "einkaufsliste",
  "version": "1.0.0",
  "type": "module",
  "private": true,
  "scripts": {
    "start": "node index.js",
    "zaehlen": "node zaehlen.js"
  }
}

Eigene Namen gehen auch, sie brauchen dann npm run davor. start und test sind die zwei Ausnahmen, bei denen das run entfallen darf.

Und noch ein Vorteil, der leicht untergeht: Was in scripts steht, ist dokumentiert. Der lange Befehl mit den drei Optionen steht an einer Stelle, statt in der Bash-Historie von drei verschiedenen Leuten.

Was passiert, wenn type fehlt

Früher war das ein harter Fehler: Ein import in einer .js-Datei ohne "type": "module" brach mit SyntaxError: Cannot use import statement outside a module ab.

Aktuelle Node-Versionen sind nachsichtiger geworden. Sie versuchen die Datei erst als CommonJS zu lesen, merken am import, dass das nicht aufgeht, und lesen sie noch einmal als ES-Modul. Dein Programm läuft also, aber du bekommst eine Warnung auf den Fehlerkanal, in der genau das steht: Die Datei wurde zweimal gelesen, das kostet Zeit, und du sollst "type": "module" eintragen.

Nimm diese Warnung ernst, auch wenn nichts abstürzt. Sie bedeutet, dass Node bei jedem Start raten muss, was du gemeint hast. Und in einem Projekt mit vielen Dateien ist das nicht mehr nur ein Schönheitsfehler.

Die Datei ist auch ein Sicherheitsthema

Ein letzter Punkt, der in Abschnitt 15 wiederkommt. Alles, was in der package.json steht, ist öffentlich, sobald das Projekt veröffentlicht wird: Namen, Versionen, Abhängigkeiten, deine Mailadresse im author-Feld.

Zugangsdaten haben hier also nichts verloren, auch nicht in einem scripts-Eintrag. Dafür gibt es die .env aus Lektion 4.2, und die steht in der .gitignore.

Zum Mitnehmen

Ab hier heißen deine Dateien .js statt .mjs. Den Unterschied macht eine einzige Zeile: "type": "module".

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, auf dem Server geprüft

    Öffnet sich mit dem Basis Konto.