Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen aus Lektion I3.3. package.json sagt "module". Was gibt node tools.cjs aus?
// package.json
{"type": "module"}
// tools.cjs
const path = require("node:path");
console.log(path.basename("/docs/notes.txt"));// I3.4 · ca. 36 Min. · Aufbau
Nach dieser Lektion fügen Sie einem Projekt mit npm Pakete hinzu, nutzen sie in Ihrem Code per Namen und starten die Aufgaben des Projekts als npm-Skripte.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
// package.json
{"type": "module"}
// tools.cjs
const path = require("node:path");
console.log(path.basename("/docs/notes.txt"));Vorhersagen · Aufgabe 2 von 7
npm install tiny-caseÜben · Aufgabe 3 von 7
npm install ____ say-hiÜben · Aufgabe 4 von 7
Üben · Aufgabe 5 von 7
{
"scripts": {
"greet": "say-hi there"
}
}Denksport · Aufgabe 6 von 7
// package.json
{
"name": "app",
"version": "1.0.0",
"scripts": {
"posttest": "node step.js post",
"test": "node step.js test",
"pretest": "node step.js pre"
}
}Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
In diesem Projekt lief npm install tiny-case, package.json führt also "tiny-case": "^2.1.0" unter dependencies, und das Paket liegt in node_modules/tiny-case. main.js importiert es per reinem Namen. Die zwei Dateien des Pakets sind ebenfalls gezeigt, damit Sie sehen, was Node.js dort findet: Seine package.json sagt über "exports", welche Datei geladen wird.
main.js
// npm install tiny-case put the package into node_modules/tiny-case.
// A bare name (no ./) is looked up in node_modules:
import {kebab} from "tiny-case";
const titles = ["Hello World", " ES Modules in Node "];
for (const title of titles) {
console.log(kebab(title));
}
node_modules/tiny-case/package.json
{"name": "tiny-case", "version": "2.1.0", "type": "module", "exports": "./index.js"}
node_modules/tiny-case/index.js
export const kebab = (text) => text.trim().toLowerCase().split(/\s+/).join("-");
Ausführen mit
node main.jsAusgabe
hello-world
es-modules-in-nodeÜbung 1 von 2
addDependency(pkg, name, version, options) gibt ein neues package.json-Objekt mit dem hinzugefügten Paket zurück, so wie npm install es speichern würde: unter devDependencies, wenn options.dev wahr ist, sonst unter dependencies; mit der genauen Version, wenn options.exact wahr ist, sonst mit ^ davor. pkg darf sich nicht ändern. Der Startcode ignoriert beide Optionen.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Wählen Sie zuerst den Feldnamen aus options.dev, dann den Bereich aus options.exact.
Ein berechneter Schlüssel, [field]: …, legt das neue Objekt unter dem gewählten Feld ab.
Spreaden Sie pkg[field] in ein neues Objekt, damit das Original unverändert bleibt.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function addDependency(pkg, name, version, options = {}) {
const field = options.dev ? "devDependencies" : "dependencies";
const range = options.exact ? version : "^" + version;
return {...pkg, [field]: {...pkg[field], [name]: range}};
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export function addDependency(pkg, name, version, options = {}) {
const dependencies = {...pkg.dependencies, [name]: "^" + version};
return {...pkg, dependencies};
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {addDependency} from './main.js';
const base = {name: 'app', version: '1.0.0', dependencies: {'tiny-case': '^2.1.0'}};
test('Ein Paket landet mit Caret unter dependencies', () => {
const pkg = addDependency(base, 'chalk', '5.6.2');
assert.deepEqual(pkg.dependencies, {'tiny-case': '^2.1.0', chalk: '^5.6.2'}, `dependencies: ${JSON.stringify(pkg.dependencies)}`);
});
test('Mit dev landet es unter devDependencies', () => {
const pkg = addDependency(base, 'say-hi', '1.0.3', {dev: true});
assert.deepEqual(pkg.devDependencies, {'say-hi': '^1.0.3'}, `devDependencies: ${JSON.stringify(pkg.devDependencies)}`);
assert.deepEqual(pkg.dependencies, {'tiny-case': '^2.1.0'}, `dependencies: ${JSON.stringify(pkg.dependencies)}`);
});
test('Mit exact hat die Version kein Caret', () => {
const pkg = addDependency(base, 'chalk', '5.6.2', {exact: true});
assert.equal(pkg.dependencies.chalk, '5.6.2', `chalk: ${pkg.dependencies.chalk}`);
});
test('Das ursprüngliche Objekt bleibt unverändert', () => {
addDependency(base, 'say-hi', '1.0.3', {dev: true});
assert.deepEqual(base, {name: 'app', version: '1.0.0', dependencies: {'tiny-case': '^2.1.0'}}, `base: ${JSON.stringify(base)}`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenÜbung 2 von 2
runOrder(scripts, name, args) gibt die Befehlszeilen zurück, die npm run name -- …args starten würde, in Reihenfolge: das pre-Skript, falls es eines gibt, dann das Skript selbst mit den angehängten Argumenten, dann das post-Skript, falls es eines gibt. Die Argumente gehen nur an das Skript selbst. Gibt es das Skript nicht, werfen Sie einen Error mit der Meldung Missing script: "name". Der Startcode gibt nur das Skript zurück.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Object.hasOwn(scripts, "pre" + name) sagt Ihnen, ob es ein pre-Skript gibt.
Hängen Sie die Argumente nur an den mittleren Befehl: [scripts[name], ...args].join(" ").
Prüfen Sie zuerst den Namen und werfen Sie, bevor Sie die Liste bauen.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function runOrder(scripts, name, args = []) {
if (!Object.hasOwn(scripts, name)) {
throw new Error('Missing script: "' + name + '"');
}
const order = [];
if (Object.hasOwn(scripts, "pre" + name)) order.push(scripts["pre" + name]);
order.push([scripts[name], ...args].join(" "));
if (Object.hasOwn(scripts, "post" + name)) order.push(scripts["post" + name]);
return order;
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export function runOrder(scripts, name, args = []) {
return [[scripts[name], ...args].join(" ")];
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runOrder} from './main.js';
const scripts = {prebuild: 'node clean.js', build: 'node build.js', postbuild: 'node zip.js', test: 'node --test'};
test('Ein Skript ohne pre und post läuft allein', () => {
const order = runOrder(scripts, 'test');
assert.deepEqual(order, ['node --test'], `order: ${JSON.stringify(order)}`);
});
test('Pre- und post-Skripte laufen um das Skript herum', () => {
const order = runOrder(scripts, 'build');
assert.deepEqual(order, ['node clean.js', 'node build.js', 'node zip.js'], `order: ${JSON.stringify(order)}`);
});
test('Argumente gehen nur an das Skript selbst', () => {
const order = runOrder(scripts, 'build', ['--watch']);
assert.deepEqual(order, ['node clean.js', 'node build.js --watch', 'node zip.js'], `order: ${JSON.stringify(order)}`);
});
test('Ein fehlendes Skript wirft Missing script', () => {
assert.throws(() => runOrder(scripts, 'biuld'), {message: 'Missing script: "biuld"'}, 'runOrder muss bei einem Namen werfen, der nicht in scripts steht');
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenimport {kebab} from "tiny-case";
console.log(kebab("Hello World"));
Was Node.js ausgibt
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'tiny-case' imported fromWarum, und die Lösung
package.json führt tiny-case vielleicht auf, aber das Paket liegt nicht in node_modules: Nach einem frischen git clone ist node_modules leer. Führen Sie zuerst npm install (oder npm ci) aus. Derselbe Fehler erscheint bei einem Tippfehler im Paketnamen.
import {kebab} from "tiny-case/index.js";
console.log(kebab("Hello World"));
Was Node.js ausgibt
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './index.js' is not defined by "exports"Warum, und die Lösung
Das Feld "exports" des Pakets führt auf, was Sie importieren dürfen, und der Pfad seiner eigenen index.js steht nicht auf dieser Liste. Importieren Sie das Paket per Namen: import {kebab} from "tiny-case". Pfade in ein Paket können sich mit jedem Update ändern; die exportierten Namen sind das, was das Paket verspricht.
import kebab from "tiny-case";
console.log(kebab("Hello World"));
Was Node.js ausgibt
SyntaxError: The requested module 'tiny-case' does not provide an export named 'default'Warum, und die Lösung
tiny-case ist ein ES-Modul, das kebab benannt exportiert und keinen Default-Export hat. Nutzen Sie Klammern: import {kebab} from "tiny-case". Die README eines Pakets zeigt, wie es zu importieren ist; steht dort import x from …, hat es einen Default-Export.
JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.