14 KiB
Einstieg in JavaScript-Dialekte und TypeScript-Konfiguration
✨ Ziel dieses Dokuments
Diese Anleitung richtet sich an Anfänger, die lernen wollen, wann sie welchen JavaScript-Dialekt (CommonJS vs. ESM) verwenden sollten, wie sie TypeScript korrekt konfigurieren und worauf sie bei modernen Projekten achten müssen.
Inhalt
- Einstieg in JavaScript-Dialekte und TypeScript-Konfiguration
🔢 Begriffe erklärt
JavaScript-Dialekte (Modulsysteme)
Name | Kürzel | Typ | Verwendung heute |
---|---|---|---|
CommonJS | CJS | require() |
Ältere Node.js-Projekte |
ECMAScript Modules | ESM | import |
Browser, moderne Tools |
- CommonJS: Nutzt
require()
undmodule.exports
. Standard bis Node 12. - ESM: Nutzt
import
/export
. Standard im Browser und in Node ab Version 14+.
Was ist TypeScript?
TypeScript ist eine statisch typisierte Obermenge von JavaScript, die zu normalem JS kompiliert wird.
🔍 Wann verwende ich was?
Ziel | Modulformat | Empfehlung | Grund |
---|---|---|---|
📅 Moderne Webanwendung | ESM | Ja | Browser erwartet ESM |
📄 Node.js CLI-Tool | ESM oder CJS | Beides möglich | ESM zukunftssicher, CJS maximal kompatibel |
🔐 Legacy-Node-Integration | CJS | Ja | Viele NPM-Pakete sind CJS-only |
🔌 Electron Renderer | ESM | Ja (Pflicht) | Chromium-only, kein CJS |
🔁 Vite/Webpack-Projekt | ESM | Ja | Toolchain basiert auf ESM |
🔧 TypeScript richtig konfigurieren
Eine vollständige Zusammenfassung zu ESM (ECMAScript Modules) – wann du es verwenden kannst, solltest oder musst, sowie alle wesentlichen technischen Eigenschaften. Stil und Umfang entsprechen exakt der vorherigen CommonJS-Zusammenfassung.
📦 Was ist ESM?
ESM (ECMAScript Modules) ist das moderne Modulsystem von JavaScript:
- verwendet
import
/export
-Syntax - wird nativ von allen modernen Browsern und Node.js (ab v14+) unterstützt
- ist Standard in allen modernen JS-Toolchains (Vite, Webpack, esbuild, etc.)
// ESM-Stil
import fs from 'node:fs/promises';
export function read(path) {
return fs.readFile(path, 'utf-8');
}
✅ Wann kann/sollte/muss man ESM verwenden?
🟢 Du kannst ESM verwenden, wenn
- du mit modernen Node.js-Versionen (v16+) arbeitest
- du ein Frontend-Tool oder ein Browser-kompatibles Projekt baust
- du Tree-Shaking oder Dynamic
import()
nutzen willst - du Typkonsistenz mit dem Browser willst (gleiche Syntax wie dort)
🟡 Du solltest ESM verwenden, wenn
Situation | Grund |
---|---|
🌐 Du entwickelst Webanwendungen mit Vite, Nuxt, Webpack o. ä. | Diese Tools basieren auf ESM |
💡 Du möchtest moderne Syntax und Tooling nutzen | ESM ist Standard |
🔄 Du willst import() dynamisch verwenden |
Nur in ESM verfügbar |
📚 Du schreibst eine wiederverwendbare Bibliothek für neue Projekte | Zukunftssicherheit |
🧩 Du verwendest Deno, Bun oder moderne Plattformen | ESM only |
🔴 Du musst ESM verwenden, wenn
- du im Browser arbeitest (ohne Bundler) → dort ist
import
Pflicht - du in Electron-Renderer-Prozessen arbeitest
- du ein Projekt hast mit
"type": "module"
und.js
-Dateien → dann interpretiert Node sie nur als ESM - du ESM-only-Dependencies nutzt (z. B.
chalk@5
,node-fetch@3
)
⚙️ TypeScript-Konfiguration für ESM
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
Und in der package.json
:
{
"type": "module"
}
Wichtig: Ohne "type": "module"
behandelt Node deine .js
-Dateien nicht als ESM, sondern als CommonJS.
📌 Merkmale von ESM
Merkmal | ESM |
---|---|
Import-Syntax | import , export |
Export-Syntax | export default , export {...} |
Dateiendung .js |
.js nur mit "type": "module" |
.mjs |
explizit ESM |
__dirname , __filename |
❌ nicht vorhanden, nur via import.meta.url |
Dynamische Imports | ✅ await import('...') |
Tree Shaking | ✅ möglich |
Browser-kompatibel | ✅ nativ |
CommonJS-Interop | ❗ mit Einschränkungen (createRequire ) |
⚠️ Besonderheiten und Stolperfallen
Problem | Lösung |
---|---|
❌ __dirname /__filename fehlen |
nutze import.meta.url + fileURLToPath() |
❌ require() nicht verfügbar |
verwende import , oder createRequire() |
❌ .js muss beim Import angegeben werden |
z. B. import './utils.js' |
❌ viele alte Pakete sind nicht ESM-kompatibel | ggf. CommonJS verwenden |
✅ Fazit ESM
ESM ist der offizielle Standard für moderne JavaScript-Entwicklung – sowohl im Browser als auch in modernen Node.js-Umgebungen.
Du solltest ESM verwenden, wenn du:
- neue Projekte startest,
- moderne Toolchains nutzt,
- oder langfristige Kompatibilität willst.
In Zweifelsfällen gilt: Wenn du mit aktuellen Tools und Node-Versionen arbeitest, nimm ESM. Nur bei Problemen mit alten Paketen oder Tooling solltest du temporär auf CommonJS zurückfallen.
🌐 CommonJS-Konfiguration CJS (Alternative)
📦 Was ist CommonJS?
CommonJS (CJS) ist das ursprüngliche Modulsystem von Node.js:
- verwendet
require()
zum Importieren - verwendet
module.exports
oderexports
zum Exportieren - keine native Unterstützung für
import
/export
- funktioniert nur in Node.js (nicht im Browser ohne Bundler)
// CommonJS-Stil
const fs = require('fs');
module.exports = { read: fs.readFileSync };
✅ Wann kann/sollte/muss man CommonJS verwenden?
🟢 Du kannst CJS verwenden, wenn
- du ein CLI-Tool oder Node.js-Skript erstellst
- du maximale Kompatibilität ohne ESM-Komplikationen willst
- du keine modernen ESM-Features brauchst
- du auf Build-Tools verzichtest und direkt
.js
-Dateien startest
🟡 Du solltest CJS verwenden, wenn
Situation | Grund |
---|---|
🔄 Du arbeitest mit älteren Node.js-Versionen (z. B. v12 oder v10) | ESM ist dort nicht stabil |
📦 Du nutzt NPM-Pakete, die kein ESM unterstützen | require() wird erwartet |
🧪 Du verwendest alte Tools, Tests oder Konfigurationen | z. B. alte mocha , gulpfile.js , webpack.config.js |
🧱 Du brauchst direkten Zugriff auf __dirname , __filename |
Diese fehlen in ESM |
📜 Du möchtest .js -Dateien ohne .mjs oder type: module nutzen |
CommonJS macht keine Vorgaben für Dateiendungen |
🔴 Du musst CJS verwenden, wenn
- das Node.js-Modul, das du importieren willst, nur
module.exports
exportiert (kein ESM-Support) - dein Projekt oder Tool nicht mit ESM kompatibel ist (ältere Tooling oder NPM-Module)
- du
require()
oder dynamisches Laden (require(dynamicPath)
) verwendest, was in ESM nicht geht
⚙️ TypeScript-Konfiguration für CJS
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
}
}
Und in der package.json
:
{
"type": "commonjs"
}
Hinweis: Das "type"
-Feld ist für Node wichtig, nicht für TypeScript.
📌 Merkmale von CommonJS
Merkmal | CommonJS |
---|---|
Import-Syntax | require() |
Export-Syntax | module.exports = … |
Dateiendung | .js (keine .mjs nötig) |
Direkt ausführbar | ✅ Ohne zusätzliche Flags |
__dirname , __filename |
✅ verfügbar |
Browserkompatibilität | ❌ Nur mit Bundler möglich |
Dynamische Importe | ✅ require(dynamicPath) |
Tree Shaking | ❌ nicht möglich |
✅ Fazit CommonJS
CommonJS ist stabil, weit verbreitet und maximal kompatibel. Wenn du einfach nur ein Node-Tool oder CLI-Skript baust und keine besonderen Build-Prozesse oder Browser-Kompatibilität brauchst: Nutze CommonJS.
Für moderne ESM-Projekte im Web oder wenn du zukunftssicher entwickeln willst, solltest du auf ESM setzen – aber CJS bleibt in vielen Fällen die einfachste und robusteste Wahl.
📄 Fazit: Empfehlungen
- Neue Projekte: Nutze ESM mit
"type": "module"
- Bestehende Tools nutzen
require()
? Dann CJS - Browser + Node gemeinsam nutzen? ESM-only + klare Trennung von
shared/
,client/
,server/
- Tooling wie Vite, Nuxt, Webpack? Immer ESM
📁 Dateiendungen in Node.js
Dateiendung | Verhalten |
---|---|
.js |
Hängt von type ab |
.mjs |
Immer ESM |
.cjs |
Immer CommonJS |
⚠️ Typische Fehler vermeiden
-
SyntaxError: Cannot use import statement outside a module
→type
fehlt inpackage.json
-
Cannot find module
bei relativen Imports →.js
fehlt am Ende beim ESM-Import -
__dirname
ist not defined → Du nutzt ESM, verwendeimport.meta.url
🚀 CLI-Build-Tipps (tsc)
npx tsc # Kompiliert Projekt laut tsconfig.json
chmod +x dist/index.js # Macht CLI-Datei ausführbar
Header für CLI-Datei:
#!/usr/bin/env node
📍 Weiterführende Themen
- Dual-Exports für NPM (ESM + CJS gleichzeitig)
- "exports"-Feld in
package.json
- Tools wie
tsup
,vite
,esbuild
als Alternativen zutsc
- Einstieg in CLI-Tools:
commander
,yargs
,chalk
,ora