346 lines
13 KiB
Markdown
346 lines
13 KiB
Markdown
# 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`
|