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

346 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`