TuBrief
구독 채널
비디오
커뮤니티

Stolpersteine und Lösungen beim Umstieg von einem pnpm-Monorepo auf Nub

TuBrief 편집팀
2026년 7월 27일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Deutsch한국어EnglishEspañol中文हिन्दीFrançaisPortuguêsРусскийالعربيةBahasa Indonesia日本語

관련 영상

There's a NEW Package Manager!? (Bun Alternative)8:29

There's a NEW Package Manager!? (Bun Alternative)

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Stolpersteine und Lösungen beim Umstieg von einem pnpm-Monorepo auf Nub

Das Node.js-Ökosystem ist erschöpft. Eine Build-Umgebung, die schichtweise auf tsx, dotenv-cli, nvm und pnpm aufgebaut ist, ist schwerfällig, und bei jedem kleinen Update geraten die Skripte durcheinander. Als Nub, ein in Rust geschriebenes All-in-One-Toolkit, auf den Plan trat und versprach, dieses Paket-Chaos in einer einzigen Binärdatei zu bündeln, war ich ehrlich gesagt erfreut, aber auch skeptisch.

Der tatsächliche Umstieg eines gewachsenen pnpm-workspace-Monorepos auf Nub erwies sich als ziemlich attraktiv. Allerdings lief natürlich nichts völlig reibungslos. Von Abhängigkeitskonflikten über eine 24-Stunden-Sicherheits-Sperrfrist bis hin zu Problemen bei der CI-Cache-Trennung – es tauchten Hürden auf, die einen in der Praxis direkt treffen.

Wie man den Abhängigkeitsbaum beim Workspace-Umstieg in den Griff bekommt

Nubs Paket-Engine aube erkennt das bestehende pnpm-workspace.yaml sowie die workspaces in der package.json auf Anhieb. Wie von der Dokumentation versprochen – voll kompatibel mit dem Schema von pnpm-lock.yaml v9 bis auf Byte-Ebene –, nutzt sie standardmäßig die bestehende virtuelle Store-Struktur (node_modules/.store/).

Das Problem sind ältere Tools, die stiltschweigend eine flache (hoisted) node_modules-Struktur voraussetzen. Führt man sie direkt nach der Migration aus, stürzen sie mit einem MODULE_NOT_FOUND-Fehler ab. Um den Dienst vorerst am Laufen zu halten, sollte man mit der Option --node-linker hoisted starten, um den Paketbaum flachzuklopfen.

Bei einer Warm-Installation mit angewendetem Cache benötigt der Standard-GVS-Modus 346 ms. Der Hoisted-Modus ist mit 1461 ms mehr als viermal langsamer, aber immer noch mehr als doppelt so schnell wie pnpm v10+ mit 3453 ms. Für den Anfang fährt man am entspanntesten, wenn man sich die Kompatibilität über den Hoisted-Modus sichert und erst nach dem Entfernen der Abhängigkeiten zu veralteten Tools auf den Standard-GVS-Modus wechselt.

`bash
#!/usr/bin/env bash
set -euo pipefail

echo "==> [1/4] Nub-Binärdatei überprüfen"
if ! command -v nub &> /dev/null; then
echo "Error: Nub ist nicht installiert. Bitte zuerst 'npm i -g @nubjs/nub' ausführen."
exit 1
fi

echo "==> [2/4] pnpm-lock.yaml Schema-Check"
if [ -f "pnpm-lock.yaml" ]; then
nub pm use nub
fi

echo "==> [3/4] Ausführungs-Engine in package.json angeben"
node -e '
const fs = require("fs");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
pkg.devEngines = pkg.devEngines || {};
pkg.devEngines.packageManager = {
name: "nub",
version: "^0.4.0",
onFail: "warn"
};
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2) + "\n");
'

echo "==> [4/4] Lockfile generieren"
nub install --frozen-lockfile=false

`

Wenn man pnpm-lock.yaml mit diesem Skript in nub.lock konvertiert, spart man sich pro Woche mehr als 2 Stunden Zeit, die vorher für das Reparieren von Skripten draufgingen.

24-Stunden-Release-Altersbeschränkung und Umgang mit dringenden Hotfixes

Nub hat ziemlich strenge Sicherheitsrichtlinien. Lifecycle-Skripte werden standardmäßig blockiert, und ohne eine npm Provenance-Signatur wird ein ERR_NUB_TRUST_DOWNGRADE geworfen. Am meisten überrascht jedoch die Option minimumReleaseAge. Paketversionen, die vor weniger als 24 Stunden veröffentlicht wurden, gelten als ausstehend in der Sicherheitsprüfung und werden an der Installation gehindert.

Im Alltag ist das ein hervorragender Schutzschild, aber wenn eine Zero-Day-Schwachstelle auftaucht und man eine vor einer Stunde erschienene Patch-Version sofort deployen muss, wird es zur Mauer der Verzweiflung. In diesem Fall muss man die erlaubten Build-Skript-Pakete in der Root-package.json explizit angeben und mit Befehlen freischalten.

`json
{
"name": "@org/monorepo-root",
"private": true,
"allowBuilds": {
"esbuild": true,
"sharp": true,
"@fast-cve/patch-pkg": true
}
}

`

Der Ablauf zum manuellen Einspielen eines blockierten Hotfix-Pakets sieht wie folgt aus:

`bash

1. Hotfix-Paket (jünger als 24h) manuell genehmigen und hinzufügen

nub add --allow-build=@fast-cve/patch-pkg @fast-cve/patch-pkg@1.0.1-hotfix

2. Build-Skripte in der Warteschlange gesammelt genehmigen

nub approve-builds

`

Durch Ausführen von nub approve-builds wird die Sperrliste aufgehoben und der Build sofort fortgesetzt. Pakete, die in der OSV-Datenbank als Schadcode (MAL-*) registriert sind, lassen sich selbst mit diesem Befehl nicht erzwingen – in solchen Fällen muss man nach einer höheren Ausweichversion suchen.

Trennung der Cache-Layer in GitHub Actions und Docker

Um die CI/CD-Geschwindigkeit zu maximieren, muss man die Cache-Pfade von Nub kennen. Die Node-Binärdatei landet in ~/.cache/nub/node/<version>/, während der Paket-CAS (Content-Addressable Store) auf ~/.cache/nub/ und node_modules/.store/ aufgeteilt wird.

In Docker Multi-Stage-Builds erzielt man den besten Caching-Effekt, indem man den Cache-Mount von BuildKit nutzt, um die Installationsschicht vollständig zu isolieren.

`dockerfile
FROM ghcr.io/nubjs/nub:latest AS base
WORKDIR /app

FROM base AS dependencies
COPY package.json nub.lock pnpm-workspace.yaml ./
COPY packages/core/package.json ./packages/core/
COPY packages/api/package.json ./packages/api/

Cache mit BuildKit Cache-Mount wiederverwenden

RUN --mount=type=cache,target=/root/.cache/nub
nub ci --prefer-offline

FROM dependencies AS builder
COPY . .
RUN nub run build --filter=@org/api

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

COPY --from=builder /app/packages/api/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000
CMD ["node", "dist/index.js"]

`

In GitHub Actions bindet man anstelle von actions/setup-node einfach nubjs/setup-nub@v0 ein.

`yaml
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

  - uses: nubjs/setup-nub@v0
    with:
      cache: true

  - run: nub ci
  - run: nub -r run build
  - run: nub -r run test

`

Die Geschwindigkeit von nub ci in Kombination mit setup-nub und Cache liegt bei rund 346 ms. Im Vergleich zu bisherigem pnpm (3453 ms) verkürzt sich die Zeit für die Paketinstallation in der Pipeline drastisch, wodurch sich die gesamte CI-Build-Zeit halbiert. Wenn man am Monatsende auf die Cloud-Infrastruktur-Abrechnung schaut, hebt das definitiv die Stimmung.

Einheitliche Entwicklungsumgebung fürs Team per Shell-Wrapper

Nub bringt einen integrierten Speicher-Transpiler auf oxc-Basis mit, sodass TypeScript-Code direkt ohne tsx oder ts-node ausgeführt werden kann. .env-Dateien werden ebenfalls automatisch eingelesen. Da der Overhead beim Bootstrappen des Node.js-Prozesses – der bei pnpm run (442,7 ms) jedes Mal auftrat – entfällt, sinkt die Skript-Ausführungszeit mit nub run auf extrem schnelle 14,7 ms. Der Unterschied ist spürbar.

Um eine Fragmentierung der Node.js-Versionen im Team zu verhindern, hinterlegt man einfach eine .node-version im Root-Verzeichnis.

`bash
echo "22.15.0" > .node-version
nub src/index.ts

`

Ab Node 22.15.0 verschwindet die Cold-Start-Verzögerung dank synchronem module.registerHooks() vollständig. Wenn neue Teammitglieder hinzustoßen, ist das Einrichten eines Automatisierungsskripts der sauberste Weg, um die Umgebung ohne lange Erklärungen auf Anhieb abzugleichen.

`bash
#!/usr/bin/env bash
set -euo pipefail

echo "==> Starte Setup der Entwicklungsumgebung"

if ! command -v nub &> /dev/null; then
if command -v brew &> /dev/null; then
brew install nubjs/tap/nub
else
npm install -g --ignore-scripts=false @nubjs/nub
fi
fi

pnpm- und npm-Befehle automatisch an die Nub-Engine umleiten

nub pm shim
nub node install
nub install

if [ ! -f ".env.local" ] && [ -f ".env.example" ]; then
cp .env.example .env.local
fi

echo "==> Setup abgeschlossen. Starten Sie mit 'nub run dev'."

`

Wenn man einmal nub pm shim ausgeführt hat, werden selbst gewohnheitsmäßig eingegebene Befehle wie pnpm install oder npm run von Nub abgefangen und verarbeitet. Neben der Reduzierung des CLI-Execution-Overheads von pnpm exec (191 ms) auf nubx (11 ms) spart man sich pro Woche mindestens 2 Stunden Debugging-Zeit für Sätze wie "Auf meinem Rechner funktioniert es aber".