# 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](#einstieg-in-javascript-dialekte-und-typescript-konfiguration) - [✨ Ziel dieses Dokuments](#-ziel-dieses-dokuments) - [Inhalt](#inhalt) - [🔢 Begriffe erklärt](#-begriffe-erklärt) - [JavaScript-Dialekte (Modulsysteme)](#javascript-dialekte-modulsysteme) - [Was ist TypeScript?](#was-ist-typescript) - [🔍 Wann verwende ich was?](#-wann-verwende-ich-was) - [🔧 TypeScript richtig konfigurieren](#-typescript-richtig-konfigurieren) - [📦 Was ist ESM?](#-was-ist-esm) - [✅ Wann kann/sollte/muss man **ESM** verwenden?](#-wann-kannsolltemuss-man-esm-verwenden) - [🟢 **Du kannst ESM verwenden**, wenn](#-du-kannst-esm-verwenden-wenn) - [🟡 **Du solltest ESM verwenden**, wenn](#-du-solltest-esm-verwenden-wenn) - [🔴 **Du musst ESM verwenden**, wenn](#-du-musst-esm-verwenden-wenn) - [⚙️ TypeScript-Konfiguration für ESM](#️-typescript-konfiguration-für-esm) - [📌 Merkmale von ESM](#-merkmale-von-esm) - [⚠️ Besonderheiten und Stolperfallen](#️-besonderheiten-und-stolperfallen) - [✅ Fazit ESM](#-fazit-esm) - [🌐 CommonJS-Konfiguration CJS (Alternative)](#-commonjs-konfiguration-cjs-alternative) - [📦 Was ist CommonJS?](#-was-ist-commonjs) - [✅ Wann kann/sollte/muss man **CommonJS** verwenden?](#-wann-kannsolltemuss-man-commonjs-verwenden) - [🟢 **Du kannst CJS verwenden**, wenn](#-du-kannst-cjs-verwenden-wenn) - [🟡 **Du solltest CJS verwenden**, wenn](#-du-solltest-cjs-verwenden-wenn) - [🔴 **Du musst CJS verwenden**, wenn](#-du-musst-cjs-verwenden-wenn) - [⚙️ TypeScript-Konfiguration für CJS](#️-typescript-konfiguration-für-cjs) - [📌 Merkmale von CommonJS](#-merkmale-von-commonjs) - [✅ Fazit CommonJS](#-fazit-commonjs) - [📄 Fazit: Empfehlungen](#-fazit-empfehlungen) - [📁 Dateiendungen in Node.js](#-dateiendungen-in-nodejs) - [⚠️ Typische Fehler vermeiden](#️-typische-fehler-vermeiden) - [🚀 CLI-Build-Tipps (tsc)](#-cli-build-tipps-tsc) - [📍 Weiterführende Themen](#-weiterführende-themen) --- ## 🔢 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()` und `module.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.) ```js // 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 ```jsonc { "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "node", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true } } ``` Und in der `package.json`: ```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` oder `exports` zum Exportieren - keine native Unterstützung für `import`/`export` - funktioniert nur in Node.js (nicht im Browser ohne Bundler) ```js // 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 ```jsonc { "compilerOptions": { "target": "ES2020", "module": "CommonJS", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true } } ``` Und in der `package.json`: ```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 in `package.json` - **`Cannot find module` bei relativen Imports** → `.js` fehlt am Ende beim ESM-Import - **`__dirname` ist not defined** → Du nutzt ESM, verwende `import.meta.url` --- ## 🚀 CLI-Build-Tipps (tsc) ```bash npx tsc # Kompiliert Projekt laut tsconfig.json chmod +x dist/index.js # Macht CLI-Datei ausführbar ``` Header für CLI-Datei: ```ts #!/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 zu `tsc` - Einstieg in CLI-Tools: `commander`, `yargs`, `chalk`, `ora`