|
| 1 | +--- |
| 2 | +title: 'Angular mit pnpm: sichere Dependencys und Best Practices' |
| 3 | +author: Danny Koppenhagen |
| 4 | +mail: mail@k9n.dev |
| 5 | +published: 2026-08-13 |
| 6 | +lastModified: 2026-08-13 |
| 7 | +keywords: |
| 8 | + - Angular |
| 9 | + - pnpm |
| 10 | + - Corepack |
| 11 | + - Supply Chain Security |
| 12 | + - Package Manager |
| 13 | + - npm |
| 14 | + - Security |
| 15 | + - Dependencies |
| 16 | + - minimumReleaseAge |
| 17 | +language: de |
| 18 | +header: angular-pnpm.jpg |
| 19 | +--- |
| 20 | + |
| 21 | +Die Zeiten, in denen der Paketmanager *npm* alternativlos war, sind längst vorbei. |
| 22 | +Mit **pnpm** steht ein alternativer Paketmanager zur Verfügung, der effizienter mit Speicherplatz umgeht, schneller installiert und moderne Sicherheitsmechanismen gegen Supply-Chain-Angriffe mitbringt. |
| 23 | + |
| 24 | +In diesem Artikel richten wir ein Angular-Projekt mit pnpm ein, konfigurieren eine sichere Entwicklungsumgebung und schauen uns Best Practices an, die sich in professionellen Teams bewährt haben: von Supply-Chain-Security bis hin zu reproduzierbaren Builds. |
| 25 | + |
| 26 | +## Inhalt |
| 27 | + |
| 28 | +[[toc]] |
| 29 | + |
| 30 | +## Warum überhaupt pnpm? |
| 31 | + |
| 32 | +npm funktioniert, ist überall vorinstalliert und die meisten Tutorials verwenden es. |
| 33 | +Warum also wechseln? |
| 34 | +Die Antwort liegt in den architektonischen Entscheidungen, die pnpm anders trifft: |
| 35 | + |
| 36 | +**Content-addressable Store:** |
| 37 | +Jede Paketversion wird genau einmal in einem zentralen Store gespeichert. |
| 38 | +Mehrere Projekte referenzieren dasselbe Paket per Hardlink, was erheblich Speicherplatz spart. |
| 39 | + |
| 40 | +**Strikte `node_modules`-Struktur:** |
| 41 | +pnpm erstellt keine flache `node_modules`-Struktur, sondern nutzt Symlinks, bei denen jedes Paket nur auf seine deklarierten Abhängigkeiten zugreifen kann. |
| 42 | +Das verhindert das *Phantom-Dependency*-Problem: Code kann nicht versehentlich auf transitive Abhängigkeiten zugreifen. |
| 43 | + |
| 44 | +**Schnellere Installationen:** |
| 45 | +Durch den zentralen Store und Hardlinks sind Installationen deutlich schneller, insbesondere bei wiederholten Installationen und in CI-Pipelines. |
| 46 | + |
| 47 | +**Monorepo-Unterstützung:** |
| 48 | +pnpm bietet erstklassige [Workspace-Unterstützung](https://pnpm.io/workspaces) mit Catalogs (zentrale Versionsverwaltung), dem Workspace-Protokoll und effizienter Verwaltung mehrerer Pakete. |
| 49 | + |
| 50 | +**Security by Default:** |
| 51 | +Seit Version 10 blockiert pnpm standardmäßig Lifecycle-Scripts in Dependencys. |
| 52 | +Damit wird eine ganze Kategorie von Supply-Chain-Angriffen von Haus aus verhindert. |
| 53 | + |
| 54 | +| Merkmal | npm | pnpm | |
| 55 | +|---------|-----|------| |
| 56 | +| Speicherverbrauch | hoch (jedes Projekt eigene Kopie) | niedrig (Content-addressable Store) | |
| 57 | +| Installationsgeschwindigkeit | mittel | schnell | |
| 58 | +| Phantom Dependencies | möglich (flache Struktur) | ausgeschlossen (strikte Struktur) | |
| 59 | +| Lifecycle Scripts | werden ausgeführt | standardmäßig blockiert (ab v10) | |
| 60 | +| Monorepo-Support | Workspaces (basic) | Workspaces + Catalogs | |
| 61 | +| minimumReleaseAge | ab npm 11.10 (`min-release-age`) | ab pnpm 10.16 | |
| 62 | + |
| 63 | +## Neues Angular-Projekt mit pnpm erstellen |
| 64 | + |
| 65 | +### pnpm installieren und Version fixieren |
| 66 | + |
| 67 | +Für die Schnittstelle zwischen npm und alternativen Paketmanagern wird das Modul `corepack` verwendet. |
| 68 | +Es wird seit Node.js 16.13 mitgeliefert. |
| 69 | +Der folgende Befehl aktualisiert Corepack auf die aktuelle Version. Das ist insbesondere wegen veralteter Signaturen in älteren Corepack-Versionen sinnvoll. Falls Corepack in deiner Node.js-Installation bereits aktuell ist, kannst du diesen Schritt überspringen. Anschließend aktivierst du pnpm: |
| 70 | + |
| 71 | +```bash |
| 72 | +npm install --global corepack@latest |
| 73 | +corepack enable pnpm |
| 74 | +``` |
| 75 | + |
| 76 | +### Projekt erzeugen |
| 77 | + |
| 78 | +Beim Erstellen eines neuen Projekts muss der Package Manager explizit angegeben werden. |
| 79 | +Ein einfaches `pnpm dlx @angular/cli@latest new book-monkey` reicht **nicht**: Die CLI würde trotzdem npm verwenden, da sie den aufrufenden Package Manager nicht automatisch erkennt. |
| 80 | +Stattdessen musst du der Angular CLI explizit mitteilen, welcher Paketmanager eingesetzt werden soll. |
| 81 | + |
| 82 | +```bash |
| 83 | +# Bei globaler Installation: |
| 84 | +ng new book-monkey --package-manager pnpm |
| 85 | + |
| 86 | +# Direkt ohne global installierte Angular CLI via npx: |
| 87 | +npx @angular/cli@latest new book-monkey --package-manager pnpm |
| 88 | + |
| 89 | +# Direkt mit pnpm dlx: |
| 90 | +pnpm dlx @angular/cli@latest new book-monkey --package-manager pnpm |
| 91 | +``` |
| 92 | + |
| 93 | +Nach der Erstellung wechselst du in den Projektordner und fixierst dort die verwendete Version: |
| 94 | + |
| 95 | +```bash |
| 96 | +cd book-monkey |
| 97 | +corepack use pnpm@latest |
| 98 | +``` |
| 99 | + |
| 100 | +Der Befehl ergänzt das Feld `packageManager` in der `package.json`. Corepack aktiviert dann bei allen Teammitgliedern automatisch dieselbe pnpm-Version. |
| 101 | + |
| 102 | +Das Flag `--package-manager pnpm` bewirkt zwei Dinge: |
| 103 | + |
| 104 | +1. Die Pakete werden mit pnpm installiert. |
| 105 | +2. In der `angular.json` wird `"cli": { "packageManager": "pnpm" }` eingetragen. |
| 106 | + |
| 107 | +Dieser Eintrag teilt der Angular CLI mit, welchen Package Manager sie für alle zukünftigen Operationen (`ng add`, `ng update`, etc.) verwenden soll. |
| 108 | +Die CLI delegiert dann alle Paketoperationen transparent an pnpm, z. B. `ng add @angular/cdk`, `ng update`, `ng generate` funktionieren unverändert. |
| 109 | + |
| 110 | +> **Tipp:** Als zusätzliche Absicherung gegen versehentliches `npm install` empfiehlt sich ein `preinstall`-Script: |
| 111 | +> |
| 112 | +> ```json |
| 113 | +> "scripts": { |
| 114 | +> "preinstall": "npx only-allow pnpm" |
| 115 | +> } |
| 116 | +> ``` |
| 117 | +
|
| 118 | +## Projektstruktur und `node_modules` |
| 119 | +
|
| 120 | +Wenn du zum ersten Mal ein pnpm-Projekt öffnest, stellst du fest, dass `node_modules` anders aufgebaut ist: |
| 121 | +
|
| 122 | +``` |
| 123 | +node_modules/ |
| 124 | +├── .pnpm/ ← Virtueller Store mit allen Paketen |
| 125 | +├── @angular/core ← Symlink nach .pnpm/... |
| 126 | +├── rxjs ← Symlink nach .pnpm/... |
| 127 | +└── ... |
| 128 | +``` |
| 129 | +
|
| 130 | +Jedes Paket in der obersten Ebene ist ein Symlink in den Ordner `.pnpm`, der wiederum Hardlinks zum globalen Store enthält. |
| 131 | +Die IDE-Unterstützung (TypeScript-Auflösung, Autocomplete) sowie Build-Tools (Vite, esbuild) funktionieren damit problemlos. |
| 132 | +
|
| 133 | +## Supply-Chain-Security mit pnpm |
| 134 | +
|
| 135 | +Dies ist der wichtigste Grund, warum pnpm heute nicht nur eine Performance-Optimierung ist, sondern eine bewusste Architekturentscheidung für die Sicherheit eines Projekts. |
| 136 | +
|
| 137 | +Supply-Chain-Attacken im npm-Ökosystem haben sich in den letzten Jahren dramatisch gehäuft. |
| 138 | +Einige bekannte Vorfälle: |
| 139 | +
|
| 140 | +| Vorfall | Jahr | Auswirkung | |
| 141 | +|---------|------|------------| |
| 142 | +| ua-parser-js | 2021 | Kryptominer in 8-Mio-Downloads-Paket, 4 Stunden online | |
| 143 | +| colors & faker | 2022 | Maintainer sabotierte eigene Pakete | |
| 144 | +| node-ipc | 2022 | Politisch motivierte Datei-Überschreibung | |
| 145 | +| eslint-config-prettier | 2025 | Phishing → gestohlener npm-Token → Malware via postinstall | |
| 146 | +| @ctrl/tinycolor (Shai-Hulud) | 2025 | Erster wurmartiger Angriff im npm-Ökosystem, 100+ Pakete betroffen | |
| 147 | +
|
| 148 | +Alle diese Angriffe nutzen denselben Grundmechanismus: Ein vertrauenswürdiges Paket wird kompromittiert, und bei der nächsten Installation wird Schadcode über `postinstall`-Scripts ausgeführt. |
| 149 | +pnpm adressiert diese Risiken mit konkreten, konfigurierbaren Mechanismen. |
| 150 | +
|
| 151 | +### pnpm-Features gegen Supply-Chain-Risiken |
| 152 | +
|
| 153 | +| Risiko | pnpm-Feature | Wirkung | |
| 154 | +|--------|--------------|---------| |
| 155 | +| Schadcode via `postinstall` | Lifecycle Scripts blockiert | Kein automatischer Code bei `pnpm install` | |
| 156 | +| Kompromittiertes Release | `minimumReleaseAge` | Neue Versionen erst nach Wartezeit installierbar | |
| 157 | +| Unbekannte Build Scripts | `onlyBuiltDependencies` | Nur explizit erlaubte Pakete dürfen Scripts ausführen | |
| 158 | +| Git-Dependencys mit Schadcode | `blockExoticSubdeps` | Git-hosted Deps können keine `prepare`-Scripts ausführen | |
| 159 | +| Nicht-reproduzierbare Builds | `pnpm-lock.yaml` + `--frozen-lockfile` | Exakt gleiche Installation in jedem Environment | |
| 160 | +
|
| 161 | +### Lifecycle Scripts kontrollieren |
| 162 | +
|
| 163 | +Seit pnpm 10 werden Scripts vom Typ `preinstall`, `install` und `postinstall` **nicht mehr automatisch ausgeführt**. |
| 164 | +Das ist der bedeutendste Sicherheitsunterschied zu npm. |
| 165 | +
|
| 166 | +Bei einem frischen Angular-Projekt sieht man nach `pnpm install` eine Meldung wie: |
| 167 | +
|
| 168 | +``` |
| 169 | +[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: @parcel/watcher@2.6.0, esbuild@0.28.1, lmdb@3.5.6, msgpackr-extract@3.0.4 |
| 170 | +Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts. |
| 171 | +``` |
| 172 | +
|
| 173 | +Das ist kein Fehler: pnpm teilt mit, dass einige Pakete Build-Scripts mitbringen, die nicht ausgeführt wurden. |
| 174 | +Ohne diese Scripts fehlen ggf. native Binarys (z. B. für `esbuild`). |
| 175 | +
|
| 176 | +Die Lösung: bewusste Freigabe mit `pnpm approve-builds`. |
| 177 | +Dieser Befehl zeigt interaktiv alle Pakete mit Build-Scripts an. |
| 178 | +Genehmigte Pakete werden in der Datei `pnpm-workspace.yaml` unter `onlyBuiltDependencies` gespeichert: |
| 179 | +
|
| 180 | +```yaml |
| 181 | +onlyBuiltDependencies: |
| 182 | + - '@parcel/watcher' |
| 183 | + - esbuild |
| 184 | + - lmdb |
| 185 | + - msgpackr-extract |
| 186 | +
|
| 187 | +ignoredBuiltDependencies: |
| 188 | + - puppeteer |
| 189 | +``` |
| 190 | + |
| 191 | +Wird später ein neues Paket mit Build-Scripts hinzugefügt, erscheint die Meldung erneut, und du entscheidest bewusst über die Freigabe. |
| 192 | + |
| 193 | +> **Hinweis beim Wechsel von npm:** Wenn du bisher `ignore-scripts=true` in der `.npmrc` verwendet hast, solltest du diese Einstellung bei pnpm 10+ **entfernen**. |
| 194 | +> pnpm blockiert Lifecycle Scripts von Dependencys bereits standardmäßig, auch ohne `.npmrc`-Eintrag. |
| 195 | +> Ein zusätzliches `ignore-scripts=true` würde auch die über `onlyBuiltDependencies` explizit freigegebenen Scripts blockieren und damit den granularen Freigabe-Mechanismus aushebeln. |
| 196 | +> Native Binarys (z. B. für esbuild) könnten dann trotz Freigabe nicht gebaut werden. |
| 197 | +
|
| 198 | +### `minimumReleaseAge`: Quarantäne für neue Versionen |
| 199 | + |
| 200 | +Die meisten kompromittierten Pakete werden innerhalb weniger Stunden erkannt und entfernt. |
| 201 | +`minimumReleaseAge` nutzt dieses Zeitfenster als Schutz: |
| 202 | + |
| 203 | +```yaml |
| 204 | +minimumReleaseAge: 1440 |
| 205 | +``` |
| 206 | +
|
| 207 | +Der Wert `1440` entspricht 24 Stunden (in Minuten). |
| 208 | +pnpm installiert keine Paketversion, die weniger als 24 Stunden alt ist, weder direkt noch transitiv. |
| 209 | + |
| 210 | +Zur Einordnung: Der [Angriff auf eslint-config-prettier](https://socket.dev/blog/eslint-prettier-malware) (2025) war nach 6 Stunden bereinigt, der [Shai-Hulud-Wurm](https://socket.dev/blog/shai-hulud-npm-worm) (2025) nach 12 Stunden, die [Kompromittierung von ua-parser-js](https://github.com/nicedoc/nicedoc/issues/1) (2021) nach 4 Stunden. |
| 211 | +Mit einer 24-Stunden-Quarantäne wären alle diese Angriffe ins Leere gelaufen. |
| 212 | + |
| 213 | +> **Hinweis:** `minimumReleaseAge` schützt nicht grundsätzlich vor allen Supply-Chain-Angriffen, reduziert aber effektiv das Risiko kurzfristig kompromittierter Releases. Das ist die mit Abstand häufigste Angriffsform. |
| 214 | + |
| 215 | +Seit pnpm 10.19 lässt sich mit `minimumReleaseAgeExclude` die Wartezeit für bestimmte Pakete (z. B. interne) deaktivieren: |
| 216 | + |
| 217 | +```yaml |
| 218 | +minimumReleaseAge: 1440 |
| 219 | +minimumReleaseAgeExclude: |
| 220 | + - '@my-company/*' |
| 221 | +``` |
| 222 | + |
| 223 | +### blockExoticSubdeps: Git-Dependencys absichern |
| 224 | + |
| 225 | +Seit pnpm 10.26 werden Dependencys von Git-Repositorys daran gehindert, `prepare`-Scripts auszuführen. |
| 226 | +Ausnahmen lassen sich verwalten, indem die Pakete explizit in `onlyBuiltDependencies` gelistet werden: |
| 227 | + |
| 228 | +```yaml |
| 229 | +blockExoticSubdeps: true |
| 230 | +``` |
| 231 | + |
| 232 | +### Lockfile und reproduzierbare Builds |
| 233 | + |
| 234 | +Die `pnpm-lock.yaml` ist kein optionales Artefakt, sondern eine Sicherheitsfunktion. |
| 235 | +Sie stellt sicher, dass überall exakt dieselben Paketversionen installiert werden. |
| 236 | + |
| 237 | +**Goldene Regeln:** |
| 238 | + |
| 239 | +1. **Niemals löschen**: Das Lockfile gehört ins Repository. |
| 240 | +2. **`--frozen-lockfile` in CI**: verhindert Lockfile-Aktualisierungen bei der Installation |
| 241 | +3. **Reviewen bei PRs**: Änderungen am Lockfile sollten bewusst geprüft werden. |
| 242 | + |
| 243 | +```bash |
| 244 | +# In CI-Pipelines immer verwenden: |
| 245 | +pnpm install --frozen-lockfile |
| 246 | +``` |
| 247 | + |
| 248 | +Dieses Kommando ist das Äquivalent zu `npm ci` mit `package-lock.json`. Durch die Hardlink-basierte Installation ist pnpm aber auch in CI-Pipelines deutlich schneller. |
| 249 | + |
| 250 | +## Empfohlene Konfiguration |
| 251 | + |
| 252 | +Die folgende Konfiguration fasst alle besprochenen Best Practices zusammen. |
| 253 | +Wichtig: `.npmrc` und `pnpm-workspace.yaml` gehören versioniert ins Repository, damit die Security Policies automatisch für alle Teammitglieder und CI-Pipelines gelten. |
| 254 | + |
| 255 | +### `.npmrc` |
| 256 | + |
| 257 | +```ini |
| 258 | +# Strikte Peer Dependencies: Konflikte werden als Fehler behandelt |
| 259 | +strict-peer-dependencies=true |
| 260 | +
|
| 261 | +# Keine automatische Installation von Peer Dependencies |
| 262 | +auto-install-peers=false |
| 263 | +
|
| 264 | +# Integritätsprüfung des Stores |
| 265 | +verify-store-integrity=true |
| 266 | +
|
| 267 | +# Höchste verfügbare Version bei der Auflösung bevorzugen |
| 268 | +resolution-mode=highest |
| 269 | +``` |
| 270 | + |
| 271 | +### `pnpm-workspace.yaml` |
| 272 | + |
| 273 | +```yaml |
| 274 | +packages: [] |
| 275 | +
|
| 276 | +onlyBuiltDependencies: |
| 277 | + - '@parcel/watcher' |
| 278 | + - esbuild |
| 279 | + - lmdb |
| 280 | + - msgpackr-extract |
| 281 | +
|
| 282 | +minimumReleaseAge: 1440 |
| 283 | +``` |
| 284 | + |
| 285 | +### `package.json` (Auszug) |
| 286 | + |
| 287 | +```json |
| 288 | +{ |
| 289 | + "name": "book-manager", |
| 290 | + "version": "0.0.0", |
| 291 | + "packageManager": "pnpm@x.y.z", |
| 292 | + "scripts": { |
| 293 | + "preinstall": "npx only-allow pnpm", |
| 294 | + "start": "ng serve", |
| 295 | + "build": "ng build", |
| 296 | + "test": "ng test" |
| 297 | + }, |
| 298 | + "dependencies": { |
| 299 | + "@angular/core": "^22.0.0", |
| 300 | + "@angular/common": "^22.0.0", |
| 301 | + "@angular/compiler": "^22.0.0", |
| 302 | + "@angular/platform-browser": "^22.0.0", |
| 303 | + "@angular/platform-browser-dynamic": "^22.0.0", |
| 304 | + "@angular/router": "^22.0.0", |
| 305 | + "@angular/forms": "^22.0.0", |
| 306 | + "rxjs": "^7.8.0", |
| 307 | + "zone.js": "~0.15.0" |
| 308 | + }, |
| 309 | + "devDependencies": { |
| 310 | + "@angular/compiler-cli": "^22.0.0", |
| 311 | + "typescript": "~5.8.0" |
| 312 | + } |
| 313 | +} |
| 314 | +``` |
| 315 | + |
| 316 | +## Bestehende Anwendung auf pnpm umstellen |
| 317 | + |
| 318 | +Wenn du bereits eine Angular-Anwendung wie betreibst, brauchst du kein neues Projekt zu erzeugen. Die Unterschiede zum neuen Setup beschränken sich auf die Übernahme der bestehenden Konfiguration und Lockfile: |
| 319 | + |
| 320 | +1. **Arbeitsstand sichern:** Lege einen Git-Branch an und prüfe, dass die Anwendung vor der Migration funktioniert. |
| 321 | +2. **pnpm-Version festlegen:** Führe im Projektverzeichnis `corepack use pnpm@latest` aus. Corepack ergänzt das `packageManager`-Feld in der vorhandenen `package.json` und trägt die konkret aufgelöste Version ein. |
| 322 | +3. **Angular CLI konfigurieren:** Ergänze in der bestehenden `angular.json` unter `cli` die Eigenschaft `"packageManager": "pnpm"`. Andere Projekteinstellungen und der verwendete Builder bleiben unverändert: |
| 323 | +
|
| 324 | + ```json |
| 325 | + { |
| 326 | + "cli": { |
| 327 | + "packageManager": "pnpm" |
| 328 | + } |
| 329 | + } |
| 330 | + ``` |
| 331 | + |
| 332 | +4. **Lockfile übernehmen:** Liegt eine `package-lock.json` oder `yarn.lock` vor, führe zunächst `pnpm import` aus. Dadurch entsteht die `pnpm-lock.yaml`. Lösche die alte Lockfile erst, nachdem du die neue geprüft hast. |
| 333 | +5. **Abhängigkeiten neu installieren:** Entferne `node_modules` und installiere anschließend mit `pnpm install`: |
| 334 | + |
| 335 | + ```bash |
| 336 | + rm -rf node_modules |
| 337 | + pnpm install |
| 338 | + ``` |
| 339 | + |
| 340 | +6. **Automatisierung anpassen:** Ersetze in CI und lokalen Skripten `npm install` beziehungsweise `npm ci` durch `pnpm install` beziehungsweise `pnpm install --frozen-lockfile`. Prüfe außerdem direkte Aufrufe von `npx` und `npm`. |
| 341 | +7. **Migration prüfen:** Führe Build, Tests und Entwicklungsserver aus. Bei blockierten Build-Scripts entscheidest du mit `pnpm approve-builds`, welche Abhängigkeiten diese ausführen dürfen. |
| 342 | + |
| 343 | +Die ausführliche pnpm-Konfiguration aus den vorherigen Abschnitten – etwa `.npmrc`, `pnpm-workspace.yaml` und `onlyBuiltDependencies` – kannst du anschließend schrittweise übernehmen. |
| 344 | + |
| 345 | +## Fazit |
| 346 | + |
| 347 | +pnpm bietet mehr als einen schnellen Package Manager, sondern liefert Werkzeuge, um Dependency Management bewusst zu gestalten: |
| 348 | + |
| 349 | +- **Security-Features** wie `minimumReleaseAge`, kontrollierte Build-Scripts und `blockExoticSubdeps` reduzieren Risiken in der Software Supply Chain. |
| 350 | +- **Strikte `node_modules`-Isolation** verhindert Phantom Dependencies. |
| 351 | +- **Reproduzierbare Installationen** via Lockfile und `--frozen-lockfile` sichern konsistente Builds. |
| 352 | + |
| 353 | +Dabei bleibt der gewohnte Angular-Workflow vollständig erhalten, denn die CLI delegiert Installationen transparent an pnpm. |
| 354 | +Wenn du später mehrere Anwendungen oder Bibliotheken verwalten möchtest, kannst du dieses Fundament ohne Architekturbruch um Workspaces, Catalogs und Nx erweitern. |
| 355 | + |
| 356 | +## Weiterführende Links |
| 357 | + |
| 358 | +- [pnpm Dokumentation](https://pnpm.io) |
| 359 | +- [pnpm Supply-Chain-Security](https://pnpm.io/supply-chain-security) |
| 360 | +- [pnpm Catalogs](https://pnpm.io/catalogs) |
| 361 | +- [Nx mit pnpm](https://nx.dev/concepts/integrated-vs-package-based#package-based) |
| 362 | +- [Angular CLI – Package Manager Konfiguration](https://angular.dev/tools/cli/setup-local) |
| 363 | +- [Corepack Dokumentation](https://nodejs.org/api/corepack.html) |
| 364 | +- [Socket.dev – Security-Analysen zu npm-Angriffen](https://socket.dev/blog) |
| 365 | + |
| 366 | +<small>**Titelbild:** generiert mit AI, bearbeitet</small> |
| 367 | + |
| 368 | +<hr> |
| 369 | + |
| 370 | +<small>Vielen Dank an Ferdinand Malcher für das Review und das wertvolle Feedback!</small> |
0 commit comments