Publicar um pacote npm transforma código interno em uma dependência consumida por outros projetos. O processo envolve muito mais que executar npm publish: é preciso definir uma API pública estável, controlar arquivos enviados, testar o pacote empacotado, escolher acesso público ou privado, aplicar versionamento semântico e proteger credenciais de publicação.
Um bom fluxo trata o tarball gerado como artefato de produção. O conteúdo publicado é permanente para aquela versão e pode ser instalado por milhares de ambientes. Portanto, cada release deve ser reproduzível, auditável e testada como um consumidor real.
Preparando o package.json
{
"name": "@empresa/minha-biblioteca",
"version": "1.0.0",
"description": "Biblioteca de utilidades para APIs Node.js",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"engines": {
"node": ">=22"
},
"publishConfig": {
"access": "public"
}
}O nome com escopo evita colisões e identifica usuário ou organização. Pacotes com escopo são privados por padrão em alguns fluxos, então publishConfig.access ou npm publish --access public torna a intenção explícita.
Definindo a API pública
Use exports para impedir acesso acidental a arquivos internos. Se consumidores importam pacote/src/helpers.js, reorganizar diretórios vira quebra de compatibilidade. Exponha somente entradas estáveis:
{
"exports": {
".": "./dist/index.js",
"./http": "./dist/http.js",
"./package.json": "./package.json"
}
}Adicionar exports a um pacote antigo pode bloquear caminhos antes acessíveis. Faça essa migração em versão principal ou preserve temporariamente os subpaths usados.
Controlando os arquivos publicados
O campo files funciona como lista de inclusão. Ele costuma ser mais seguro que depender apenas de .npmignore. Antes de publicar, execute:
npm pack --dry-runRevise cada arquivo. Procure por:
- arquivos
.env; - chaves privadas e certificados;
- credenciais de teste;
- fixtures com dados pessoais;
- source maps contendo código sensível;
- logs e dumps;
- configurações internas;
- pastas de cobertura.
O registry não é lugar para descobrir um vazamento. Mesmo removendo uma versão, cópias podem permanecer em caches e instalações.
Build antes da publicação
Pacotes TypeScript normalmente publicam JavaScript e declarações:
{
"scripts": {
"clean": "node scripts/clean.mjs",
"typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json",
"test": "node --test",
"prepack": "npm run clean && npm run typecheck && npm test && npm run build"
}
}prepack é executado antes de npm pack e npm publish. Mantenha-o determinístico e sem depender de arquivos locais não versionados.
Testando o tarball
Gerar um pacote e instalá-lo em um projeto temporário encontra erros que testes internos não detectam:
npm pack
mkdir /tmp/teste-consumidor
cd /tmp/teste-consumidor
npm init -y
npm install /caminho/empresa-minha-biblioteca-1.0.0.tgzTeste imports, tipos, CommonJS ou ESM, arquivos auxiliares e comportamento em uma versão mínima suportada do Node.js.
Publicação pública com escopo
Autentique-se:
npm login
npm whoamiDepois:
npm publish --access publicPara publicação direta, a conta deve usar 2FA ou um token granular configurado de acordo com as exigências do npm. Prefira 2FA e tokens de escopo mínimo.
Staged publishing
O npm oferece publicação em estágio, permitindo que o CI envie o pacote para revisão antes de torná-lo público:
npm stage publish
npm stage list @empresa/minha-biblioteca
npm stage approve ID_DO_ESTAGIOA aprovação exige 2FA. Esse modelo separa criação do artefato e autorização final, reduzindo o risco de um workflow comprometido publicar diretamente.
Versionamento semântico
Use:
- patch: correções compatíveis;
- minor: funcionalidades compatíveis;
- major: mudanças incompatíveis.
npm version patch
npm version minor
npm version majorO comando altera a versão, cria commit e tag por padrão. Em automações, ferramentas de release podem assumir essa etapa.
Pré-releases e dist-tags
Para testar uma versão:
npm version prerelease --preid=beta
npm publish --tag betaConsumidores instalam com:
npm install @empresa/minha-biblioteca@betaNão publique pré-release com tag latest por engano. Consulte:
npm dist-tag ls @empresa/minha-bibliotecaREADME e documentação
O README deve incluir instalação, exemplo mínimo, requisitos de Node.js, API pública, tratamento de erros, política de suporte e licença. O exemplo precisa ser executável e acompanhar mudanças da biblioteca.
Dependências
Coloque em dependencies o que o pacote precisa em runtime. Ferramentas de build e teste ficam em devDependencies. Use peerDependencies quando o consumidor precisa fornecer uma biblioteca compartilhada, como um framework.
{
"peerDependencies": {
"fastify": "^5.0.0"
},
"peerDependenciesMeta": {
"fastify": {
"optional": true
}
}
}Faixas muito abertas podem aceitar versões incompatíveis; faixas muito fechadas criam conflitos desnecessários.
Proveniência
Workflows compatíveis podem publicar com declaração de proveniência:
npm publish --provenance --access publicA proveniência conecta o pacote ao repositório e ao workflow que produziu o artefato. Ela não substitui revisão, testes e proteção de branches, mas melhora rastreabilidade.
Trusted publishing com OIDC
Quando disponível, prefira trusted publishing em vez de token npm de longa duração. O workflow recebe credencial temporária vinculada ao repositório e ambiente autorizados. Isso elimina um segredo persistente que poderia vazar.
Configure permissões mínimas e ambiente protegido. Pull requests externos não devem ter acesso a publicação.
Workflow de GitHub Actions
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: read
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
environment: npm
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm run typecheck
- run: npm test
- run: npm run build
- run: npm pack --dry-run
- run: npm publish --provenance --access publicProteja o ambiente com aprovação quando a criticidade justificar.
Monorepos e workspaces
Cada workspace publicável precisa de nome, versão, files e exports próprios. Para publicar manualmente:
npm publish -w @empresa/minha-biblioteca --access publicNão publique o pacote raiz se ele existe apenas para orquestrar o monorepo; mantenha private: true.
Pacotes privados
Remova access: public e configure permissões da organização. Em CI, não grave tokens em imagens Docker ou logs. Arquivos .npmrc temporários devem ser removidos na mesma camada.
Deprecar uma versão
Quando uma versão tem problema, depreque com orientação:
npm deprecate '@empresa/minha-biblioteca@1.2.0' 'Use 1.2.1: corrige falha de inicialização'Deprecar informa usuários sem quebrar instalações existentes.
Unpublish não é rollback comum
Remover versões possui regras e pode quebrar consumidores. A abordagem normal é publicar uma correção e deprecar a versão anterior. Nunca reutilize o mesmo número de versão.
Checklist antes do publish
- árvore Git limpa;
- versão correta;
- changelog atualizado;
- testes e typecheck aprovados;
- tarball revisado;
- imports testados fora do monorepo;
- nenhum segredo;
- licença presente;
- tag de distribuição correta;
- Node mínimo testado.
Fluxo recomendado
Defina uma API pequena, publique somente dist e documentação, teste o tarball, use 2FA ou OIDC, gere proveniência e trate versões como imutáveis. Combine com Exports e Imports no Node.js, monorepos em npm Workspaces, versões de ferramentas com Corepack e segurança em Supply Chain no Node.js.
Consulte o guia oficial de publicação de pacotes com escopo e a referência oficial do npm publish.



