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

Migrando um monorepo pnpm para o Nub: percalços e soluções

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

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

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

관련 영상

Existe um NOVO Gerenciador de Pacotes!? (Alternativa ao Bun)8:29

Existe um NOVO Gerenciador de Pacotes!? (Alternativa ao Bun)

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
구독 채널
비디오
커뮤니티
로그인

Migrando um monorepo pnpm para o Nub: percalços e soluções

O ecossistema Node.js está exausto. Um ambiente de build construído empilhando tsx, dotenv-cli, nvm e pnpm é pesado e, a cada atualização, as scripts ficam desconfiguradas. Quando o Nub, um conjunto de ferramentas integrado feito em Rust, surgiu prometendo empacotar toda essa bagunça de pacotes em um único binário, fiquei sinceramente feliz, mas também um pouco desconfiado.

Na prática, quando migrei um monorepo pnpm-workspace em produção para o Nub, a experiência acabou se mostrando bastante atraente. Mas nada é uma transição 100% suave. Conflitos de dependências, políticas de bloqueio de segurança de 24 horas e até problemas de separação de cache em CI foram obstáculos reais com os quais me deparei no trabalho prático.

Como resolver a árvore de dependências ao migrar workspaces

O motor de pacotes do Nub, o aube, reconhece imediatamente o pnpm-workspace.yaml existente e os workspaces do package.json. Como diz a descrição de que ele é compatível byte a byte com o esquema v9 do pnpm-lock.yaml, ele utiliza por padrão a estrutura existente de Store virtual (node_modules/.store/).

O problema são as ferramentas antigas que pressupõem implicitamente uma estrutura achatada (hoisted) em node_modules. Se você executá-las logo após a migração, elas quebram emitindo o erro MODULE_NOT_FOUND. Para fazer o serviço funcionar imediatamente, é preciso começar desdobrando a árvore de pacotes com a opção --node-linker hoisted.

Considerando uma instalação Warm com cache aplicado, o modo GVS padrão leva 346 ms. O modo Hoisted leva 1461 ms, sendo mais de 4 vezes mais lento, mas ainda é mais de 2 vezes mais rápido que os 3453 ms do pnpm v10+. No início, é mais tranquilo garantir a compatibilidade com o modo Hoisted e, à medida que você remove a dependência de ferramentas antigas, migrar para o modo GVS padrão.

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

echo "==> [1/4] Verificando binário do Nub"
if ! command -v nub &> /dev/null; then
echo "Error: Nub não encontrado. Execute 'npm i -g @nubjs/nub' primeiro."
exit 1
fi

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

echo "==> [3/4] Especificando motor de execução no package.json"
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] Gerando Lockfile"
nub install --frozen-lockfile=false
`

Ao converter o pnpm-lock.yaml em nub.lock usando este script, você pode economizar mais de 2 horas por semana que costumavam ser perdidas corrigindo scripts quebradas.

Limite de idade de lançamento de 24 horas e resposta a hotfixes de emergência

O Nub possui políticas de segurança bastante rígidas. Ele bloqueia por padrão scripts de ciclo de vida e lança ERR_NUB_TRUST_DOWNGRADE se não houver a assinatura npm Provenance. O mais desconcertante é a opção minimumReleaseAge. Versões de pacotes lançadas há menos de 24 horas são consideradas em estado de espera por verificação de segurança, e a instalação é bloqueada.

No dia a dia, é um ótimo escudo defensivo, mas quando uma vulnerabilidade zero-day explode e você precisa implantar imediatamente uma versão de correção lançada há apenas 1 hora, isso vira um muro inquebrável. Nesses momentos, você deve declarar os pacotes com permissão de script de build no package.json raiz e liberá-los via comando.

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

O fluxo para contornar e aplicar um pacote de hotfix bloqueado é o seguinte:

`bash

1. Aprovação manual e adição do pacote de hotfix com menos de 24h

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

2. Aprovação em lote dos scripts de build na fila de espera

nub approve-builds
`

Ao executar nub approve-builds, a lista de bloqueio é liberada e o build continua imediatamente. Pacotes registrados como código malicioso (MAL-*) no banco de dados da OSV não serão liberados nem mesmo com este comando, portanto, nesse caso, você precisará procurar por uma versão alternativa superior.

Separação de camadas de cache no GitHub Actions e Docker

Para aumentar a velocidade do CI/CD, é necessário conhecer os caminhos de cache do Nub. Os binários do Node ficam em ~/.cache/nub/node/<version>/, e o CAS (Content-Addressable Store) dos pacotes é dividido entre ~/.cache/nub/ e node_modules/.store/.

Em builds multi-stage do Docker, você deve usar os mounts de cache do BuildKit para isolar completamente a camada de instalação para obter os benefícios do cache.

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

Reutilizando o repositório com o mount de cache do BuildKit

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"]
`

No GitHub Actions, suba o nubjs/setup-nub@v0 em vez de actions/setup-node.

`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

`

A velocidade do nub ci combinada com o setup-nub e o cache fica em torno de 346 ms. Em comparação com o pnpm anterior (3453 ms), o tempo de instalação de pacotes na pipeline é drasticamente reduzido, cortando o tempo total de build do CI pela metade. Olhar para a fatura de infraestrutura em nuvem no final do mês com certeza melhora o humor.

Padronizando o ambiente de desenvolvimento da equipe com um wrapper de shell

Como o Nub possui um transpilador em memória baseado em oxc embutido, ele executa código TypeScript diretamente sem a necessidade de tsx ou ts-node. Ele também lê arquivos .env automaticamente. O overhead de bootstrap do processo Node.js que surgia toda vez ao usar pnpm run (442,7 ms) desaparece, fazendo com que o tempo de execução de scripts do nub run caia para 14,7 ms. A diferença perceptível é enorme.

Para evitar a fragmentação de versões do Node.js entre os membros da equipe, basta fixar um .node-version na raiz.

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

No Node 22.15.0 ou superior, o atraso no cold start é completamente eliminado graças ao module.registerHooks() síncrono. Quando um novo membro entra na equipe, a maneira mais limpa de padronizar o ambiente de uma só vez, sem explicações complexas, é configurar um script de automação.

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

echo "==> Iniciando configuração do ambiente de desenvolvimento"

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

Roteia automaticamente comandos pnpm e npm para o motor do Nub

nub pm shim
nub node install
nub install

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

echo "==> Configuração concluída. Execute com 'nub run dev'."
`

Ao deixar o nub pm shim configurado, mesmo que você digite por hábito pnpm install ou npm run, o executor do Nub interceptará e processará o comando. O overhead de execução da CLI cai de pnpm exec (191 ms) para nubx (11 ms), e você ainda economiza cerca de 2 horas por semana que seriam gastas depurando frases como "no meu computador funciona".