package-lock.json erwartet. Auf Remote-Mac-CI mit grenzüberschreitendem Registry-Zugang scheitert es selten an der „falschen CPU“ — typisch sind doppelte Auflösung, inkonsistente Spiegel-URLs und Retry-Schleifen, die Lockfile-Drift maskieren. Diese Seite ist eine Entscheidungsmatrix: pro Paketwurzel eine Lockfile-Autorität, ein gemeinsamer Registry-Spiegel für beide Tools, begrenzte parallele Installation, Cache-Keys aus den richtigen Hashes plus Retry-Schwellen, die bei Integrität sofort stoppen. Einstieg ohne Login: MacPull-Startseite und Technik-Blog-Übersicht. Vertiefung zu anderen JS-Paketmanagern (ohne Git-/SPM-/Docker-Schwerpunkt): Yarn Berry PnP vs. node_modules sowie Deno / JSR grenzüberschreitend.
Ausführbare Entscheidungsmatrix (Hybrid-Workspace + grenzüberschreitende Registry)
Nutzen Sie die Tabelle als Merge-Gate: Jede Zeile braucht in YAML oder Runbook einen Verantwortlichen und einen festen Wert, bevor Sie parallele Jobs auf geteilten Apple-Silicon-Hosts hochdrehen.
Zwei Ebenen trennen: pro Job (npm-Sockets, Bun-Cache-Pfad, frozen installs) und pro Builder-Pool (wie viele Pipelines dieselbe Egress-IP und dieselbe NVMe belasten). In Multi-Tenant-Remote-Mac-Umgebungen dominiert oft die zweite Ebene — zwei vermeintlich „kleine“ Jobs mit je zwölf parallelen Sockets können trotzdem 429-Stürme auf ein gemeinsames Spiegel-VIP erzeugen. Messen Sie Fehlercodes pro Stunde und drosseln Sie Job-Parallelität, bevor Sie Tarball-Deduplizierung optimieren.
| Entscheidung | Option A | Option B | Hinweis Remote-Mac-CI (2026) |
|---|---|---|---|
| Lockfile-Autorität | Nur Bun.lockb (bzw. textuelles bun.lock bei neueren Bun-Versionen); npm install an Repo-Wurzel verbieten; bun install --frozen-lockfile |
Nur package-lock.json; Bun nur mit --no-save oder gar nicht für Dependencies |
Beide Tools dürfen Locks in CI nicht neu schreiben. Binäres Bun.lockb ist für menschliche PR-Diffs ungeeignet — gate per Checksumme + Install-Log-Artefakten statt Zeilen-Diff. |
| Registry-Spiegel | Ein Upstream über NPM_CONFIG_REGISTRY + scoped //registry.npmjs.org/:_authToken aus CI-Secrets |
Freigegebener Regionalspiegel + Allowlist; optional bunfig.toml [install].registry spiegelnd dieselbe npm-Richtlinie |
Bun liest npm-kompatible Konfiguration. Unterschiedliche Registry-URL zwischen npm ci und bun install erzeugt divergente Bäume — pro Job exakt eine URL. |
| Parallele Installation | Bun-Standardparallelität; gleichzeitige Jobs pro Mac begrenzen (Queue-Tiefe 1–2 bei schweren Monorepos) | npm config set maxsockets 12 (Start 8–16; kalibrieren gegen 429-Rate) |
Hohe WAN-RTT: Parallelität jenseits ~24 Sockets verbessert p50 oft kaum, erhöht aber 429-Risiko. |
| Cache-Key-Namen | bun-<os>-<hash(bun.lockb|bun.lock)>-<hash(package.json**)> |
npm-<os>-<hash(package-lock.json)>-<node>-<npm> |
Node-Major und npm- bzw. Bun-Semver in den Key aufnehmen, wenn Toolversion Auflösung oder optionale Abhängigkeiten beeinflusst. |
| Fehler-Retry-Schwelle | Netzwerk: max. 3 Versuche, Backoff 2s / 4s / 8s | Lockfile oder Integrität: max. 0 Retries (Job sofort fehlschlagen) | Orchestratoren: Logs auf ERESOLVE, frozen-lockfile, checksum prüfen — äußere Retry-Wrapper für diese Tokens deaktivieren. |
Operative Kurzcheckliste vor dem Merge: (1) In den CI-Logs stehen Registry-Host, Bun-Minor und npm-Minor in derselben Zeile wie der Install-Befehl. (2) Ein Canary-Job pro Woche lädt absichtlich mit künstlich verkürztem Timeout — so sehen Sie 429- und TLS-Fehler, bevor das Team sie in der Nacht produziert. (3) Artefakte: Checksumme von Bun.lockb bzw. bun.lock und Hash der package-lock.json werden als strukturierte Felder in Ihre Pipeline-JSON geschrieben, damit Webhooks und interne Dashboards Trends ohne Log-Mining erkennen.
Bun.lockb versus package-lock.json im selben Repository
Bun.lockb (oder textuelles Lock) fixiert den Graph, den Bun aufgelöst hat; package-lock.json beschreibt npm-Arborist inklusive lockfileVersion-Besonderheiten. Muss ein Unterverzeichnis aus Kompatibilitätsgründen bei npm bleiben (Legacy-postinstall, Publishing-Tooling), isolieren Sie es: eigene package.json-Wurzel mit eigenem Lockfile und dort nur npm ci, während die Workspace-Wurzel Bun nutzt. Grenze und Befehl im README dokumentieren, damit Reviewer Drift nicht mit dem falschen Tool „reparieren“.
Abnahmen, die Audits überleben: (1) CI druckt Bun- und npm-Version aus demselben Metadatenblock. (2) Frozen: bun install --frozen-lockfile an der Bun-Wurzel und npm ci in npm-only-Paketen. (3) Optionale Abhängigkeiten: npm_config_platform / npm_config_arch mit Buns Ausgabe auf darwin arm64 abgleichen, damit native Binaries konsistent auflösen.
Kopierbare Umgebungsvariablen und Befehle
Setzen Sie diese Werte zu Beginn der Install-Phase (Shell oder CI-Env-Block). Hostnamen des Spiegels durch den von Ihrer Security freigegebenen Endpunkt ersetzen.
# Grenzüberschreitungsfreundlicher Registry-Zugang (npm-Konfig lesen Bun und npm)
export NPM_CONFIG_REGISTRY="https://registry.npmjs.org/" # oder freigegebener Spiegel-URL
export NPM_CONFIG_FETCH_RETRIES="3"
export NPM_CONFIG_FETCH_RETRY_MINTIMEOUT="20000"
export NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT="120000"
export NPM_CONFIG_MAXSOCKETS="12"
# Bun-Install-Cache (warme Runner; in Multi-Tenant-Pools pro Job eigene Pfade bevorzugen)
export BUN_INSTALL_CACHE_DIR="${CI_CACHE_DIR:-$HOME/.cache/bun}/install"
# Optional: npm-Cache neben Bun-Cache im Hybrid-Job
export npm_config_cache="${CI_CACHE_DIR:-$HOME/.cache}/npm"
# --- Frozen installs (Zeile aus Matrix „Lockfile-Autorität“ wählen) ---
bun --version
bun install --frozen-lockfile
# Beispiel npm-only-Teilbaum:
# (cd packages/legacy-npm && npm ci --omit=dev)
Repo-lokal ohne Secrets in Git: bunfig.toml neben der Wurzel-package.json:
# bunfig.toml (Beispiel — Registry anpassen) [install] # registry = "https://ihr.freigegebener.spiegel.example/npm" frozenLockfile = true # optional in CI: install-Skript-Risiko reduzieren # ignoreScripts = true
- Spiegel-URL identisch in
NPM_CONFIG_REGISTRY, committed.npmrcfür Scopes und optionalbunfig.toml[install].registry. - Private
@org/*://npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_TOKEN}(oder Vault) mit read-only-Tokens. NODE_OPTIONS=--max-old-space-size=8192erst nach Messung; Speicherdruck plus parallele Installer OOMt Mac-Agenten oft vor Registry-Timeouts.
CI-Cache-Key-Snippets (GitHub Actions-Stil)
Namen schlagen Kompression: Ein schlechter Key vergiftet optional deps oder invalidiert bei jedem Commit den CDN-Cache.
# Beispiel: getrennte Caches, damit Bun-Binary-Lock den npm-Cache nicht jedes Mal verwirft
- uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lockb', 'bun.lock') }}-${{ hashFiles('**/package.json') }}
restore-keys: |
bun-${{ runner.os }}-${{ hashFiles('bun.lockb', 'bun.lock') }}-
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-node${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-node${{ matrix.node }}-
Bounded-Retry-Shell (nur Transport)
Netzwerkfehler einwickeln; bei Log-Hinweisen auf frozen lockfile oder Integrität sofort beenden — sonst täuschen äußere Retries grüne Builds bei Supply-Chain-Drift vor.
#!/usr/bin/env bash
set -euo pipefail
attempt=1 max=4 delay=2
log=bun-install-$attempt.log
while [ "$attempt" -le "$max" ]; do
log="bun-install-${attempt}.log"
if bun install --frozen-lockfile 2>&1 | tee "$log"; then exit 0; fi
if grep -qiE 'frozen.?lock|lockfile|checksum|integrity|ERESOLVE' "$log"; then exit 1; fi
sleep "$delay"; delay=$((delay * 2)); attempt=$((attempt + 1))
done
exit 1
FAQ
Dürfen Entwickler bun install und npm install abwechselnd nutzen? Nein. Pro Paketwurzel genau ein Befehl für Lock-Updates im Alltag; das andere Tool nur in dokumentierten Wartungsfenstern mit Vier-Augen-Review.
Entfällt Parallelitätsdeckel bei schnellem Spiegel? Nein. Spiegel ratenlimitieren weiter; Deckel schützen geteilten Remote-Mac-Egress und halten p95 der Warteschlange planbar.
Wo Yarn-only-Themen? Dritte Insel mit eigenem Cache-Key und Lock-Gate — oder vereinheitlichen. Siehe die Yarn-Berry-Matrix oben verlinkt.
Fazit
Bun und npm funktionieren auf Remote-Mac-CI zuverlässig, wenn jede Paketwurzel genau eine Lockfile-Autorität hat, beide Tools dieselbe Registry-Spiegel-URL lesen, parallele Installation zunächst im 8–24-Socket-Band bleibt, Cache-Keys die richtigen Lock-Artefakte plus Toolchain-Versionen hashen und Retries bei Integrität oder Lockfile sofort enden. So sinken grenzüberschreitende Flakes, ohne Drift zu verstecken.
Für Apple-Silicon-Runner-Kapazität passend zu Ihrer Registry-Strategie: macpull.com/de (Startseite, ohne Anmeldung), dazu Preise, Kaufen und die Hilfe. Wenn Sie andere JS-Pull-Matrizen vergleichen möchten, nutzen Sie erneut die Blog-Liste und die eingangs verlinkten Artikel.