adminslog/dokus/js-ts/js-ts-dialekte.md

346 lines
14 KiB
Markdown
Raw Normal View History

2025-06-27 12:58:02 +02:00
# 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`