npm Workspaces no Node.js permite gerenciar vários pacotes dentro de um único repositório. Aplicações, bibliotecas e ferramentas compartilham instalação, lockfile e comandos, enquanto continuam mantendo seus próprios arquivos package.json.
O recurso é útil em monorepos com frontend, backend, SDKs e pacotes internos. Ele reduz a necessidade de publicar versões intermediárias apenas para testar integração local, mas exige regras claras para dependências, builds, versionamento e CI.
Neste guia, você aprenderá a criar workspaces, executar scripts, referenciar pacotes locais, organizar dependências, publicar bibliotecas e evitar problemas comuns.
Estrutura básica
meu-monorepo/
package.json
package-lock.json
apps/
api/
package.json
web/
package.json
packages/
config/
package.json
logger/
package.jsonConfigurando o workspace raiz
{
"name": "plataforma",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
]
}Marque a raiz como privada para impedir publicação acidental do monorepo.
Criando um pacote interno
{
"name": "@empresa/logger",
"version": "1.0.0",
"type": "module",
"exports": "./src/index.js"
}Outro workspace pode declarar a dependência pelo nome:
{
"dependencies": {
"@empresa/logger": "1.0.0"
}
}O npm conecta o pacote local durante a instalação quando a versão é compatível.
Instalando dependência em um workspace
npm install fastify --workspace apps/apiO comando atualiza o package.json do workspace selecionado e o lockfile da raiz.
Instalando ferramenta na raiz
npm install -D eslint -w .Ferramentas compartilhadas podem ficar na raiz, desde que todos os pacotes usem configuração compatível.
Executando scripts em um pacote
npm run test --workspace @empresa/loggerTambém é possível usar o caminho do workspace:
npm run dev --workspace apps/apiExecutando em todos os workspaces
npm run test --workspacesPara ignorar pacotes sem o script:
npm run test --workspaces --if-presentNão presuma que a ordem será adequada para builds dependentes. Orquestre a sequência quando um pacote precisa ser compilado antes de outro.
Scripts na raiz
{
"scripts": {
"test": "npm run test --workspaces --if-present",
"lint": "npm run lint --workspaces --if-present",
"build": "npm run build --workspace @empresa/config && npm run build --workspace @empresa/logger && npm run build --workspace apps/api"
}
}Dependências locais
Use nomes de pacote estáveis e versões coerentes. Dependências internas devem ser declaradas, mesmo quando o código está no mesmo repositório. Imports por caminhos relativos entre workspaces quebram encapsulamento.
Não importe src de outro pacote
// evite
import { logger } from '../../../packages/logger/src/index.js';Prefira:
import { logger } from '@empresa/logger';Assim, testes e produção usam a mesma API pública.
Exports por pacote
Cada pacote deve definir suas entradas com exports. Consulte Package Exports no Node.js.
Um lockfile para o repositório
O package-lock.json da raiz registra a árvore completa. Versione o arquivo e use npm ci no pipeline.
Hoisting
O gerenciador pode instalar dependências em posições compartilhadas. Não confie que um pacote conseguirá importar dependência que não declarou. Esse erro funciona localmente e falha após publicação ou mudança de árvore.
Dependências de desenvolvimento
Decida quando uma ferramenta pertence à raiz ou ao workspace. Uma biblioteca que precisa gerar tipos no momento da publicação deve declarar a ferramenta no local adequado ao seu fluxo.
Configurações compartilhadas
Crie pacotes para ESLint, TypeScript ou testes quando várias áreas precisam da mesma base:
packages/
eslint-config/
tsconfig/
test-utils/Evite um pacote de configuração que importe recursos de produção.
Build incremental
Monorepos grandes não devem recompilar tudo a cada mudança. Mapeie dependências entre workspaces e execute apenas pacotes afetados. O npm fornece a base de workspaces, mas orquestração avançada pode exigir ferramenta adicional.
Testes unitários e integrados
Cada pacote deve possuir testes próprios. A raiz deve adicionar testes de integração entre aplicações e bibliotecas, usando as entradas públicas instaladas.
CI
npm ci
npm run lint --workspaces --if-present
npm run test --workspaces --if-present
npm run build --workspaces --if-presentEm pipelines paralelos, divida por workspace ou grupo de dependência. O artigo Test Sharding no Node.js mostra estratégias de distribuição.
Variáveis de ambiente
Aplicações podem ter configurações próprias, mas segredos não devem ficar em pacotes compartilhados. Valide cada processo conforme Variáveis de Ambiente no Node.js.
Publicando pacote individual
npm publish --workspace @empresa/loggerAntes de publicar, execute testes e confira o tarball:
npm pack --dry-run --workspace @empresa/loggerPacotes privados
{
"private": true
}Use em aplicações e bibliotecas que não devem chegar ao registry. A raiz privada não torna automaticamente todos os workspaces privados.
Versionamento
Você pode versionar pacotes de forma independente ou sincronizada. A escolha depende do grau de acoplamento e do fluxo de release.
- versões independentes reduzem releases desnecessários;
- versão única simplifica comunicação de uma plataforma integrada;
- ambas exigem changelog e testes de compatibilidade.
Migrações de dependência interna
Quando um pacote interno muda API, atualize os consumidores no mesmo pull request e execute a matriz completa. Se ele também é publicado externamente, respeite versionamento semântico.
Docker
Copiar o monorepo inteiro para cada imagem aumenta contexto e cache inválido. Copie manifests e lockfile primeiro, instale, depois adicione apenas fontes necessárias.
Garanta que o pacote interno esteja presente durante o build da aplicação.
Erros comuns
- não marcar raiz como privada;
- importar src de outro workspace;
- usar dependência não declarada por causa do hoisting;
- publicar arquivo errado;
- executar builds em ordem incorreta;
- misturar segredos em pacote compartilhado;
- não testar tarball;
- manter scripts inconsistentes.
Checklist para produção
- raiz privada;
- padrões de workspace explícitos;
- nomes com escopo;
- dependências declaradas;
- exports por pacote;
- lockfile versionado;
- scripts padronizados;
- CI por workspace;
- publicação testada;
- versionamento documentado.
Conclusão
npm Workspaces no Node.js simplifica o gerenciamento de vários pacotes sem eliminar seus limites. O monorepo funciona melhor quando cada workspace possui API pública, dependências declaradas e testes próprios.
Use a raiz para coordenação, não para esconder acoplamento. Com lockfile único, scripts consistentes e releases controlados, workspaces reduzem atrito entre aplicações e bibliotecas.
Consulte a documentação oficial de npm workspaces e a referência do campo workspaces.




