Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Semantic Versioning no Node.js

Atualizado em: 9 de setembro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

O Semantic Versioning no Node.js, também chamado de SemVer, é uma convenção para comunicar o impacto de alterações em pacotes. Uma versão como 2.4.1 separa major, minor e patch. Quando o pacote segue um contrato público claro, consumidores conseguem decidir se uma atualização pode ser aplicada automaticamente ou exige migração.

SemVer não é apenas mudar números. Ele depende de uma API pública documentada, testes de compatibilidade, changelog e disciplina para reconhecer breaking changes em runtime, tipos, exports, comportamento e requisitos de ambiente.

Neste guia, você aprenderá major, minor, patch, versões pré-release, ranges do npm, zero major, breaking changes em TypeScript, peer dependencies, dist-tags e um processo seguro de release.

Formato major.minor.patch

MAJOR.MINOR.PATCH
  • Patch: correção compatível, como 1.2.3 → 1.2.4;
  • Minor: funcionalidade compatível, como 1.2.4 → 1.3.0;
  • Major: mudança incompatível, como 1.3.0 → 2.0.0.

A documentação do npm sobre semantic versioning recomenda começar pacotes estáveis em 1.0.0. A especificação completa está em semver.org.

Defina a API pública

Você só pode avaliar compatibilidade quando sabe o que é público. A API inclui:

  • funções, classes e constantes exportadas;
  • subpaths do pacote;
  • tipos TypeScript;
  • opções de configuração;
  • formato de erros;
  • eventos emitidos;
  • comandos CLI;
  • variáveis de ambiente documentadas;
  • comportamento observável.

Use Exports e Imports no package.json para limitar entry points.

Patch release

Exemplos normalmente compatíveis:

  • corrigir cálculo incorreto;
  • evitar memory leak;
  • melhorar mensagem sem contrato estruturado;
  • otimizar desempenho mantendo resultado;
  • corrigir declaração de tipo para refletir runtime;
  • atualizar dependência sem alterar API.

Uma correção pode ser breaking quando consumidores dependiam do comportamento antigo, mesmo que fosse um bug. Avalie impacto real.

Minor release

Exemplos:

  • nova função exportada;
  • nova opção opcional;
  • novo subpath;
  • novo método sem conflito;
  • novo evento que consumidores podem ignorar;
  • suporte adicional a uma versão do Node.js.

Adicionar valor a um enum TypeScript pode quebrar switch exaustivo. Nem toda adição é automaticamente compatível.

Major release

Exemplos de breaking change:

  • remover ou renomear export;
  • mudar parâmetros obrigatórios;
  • alterar tipo de retorno;
  • mudar CommonJS para ESM sem estratégia;
  • remover subpath;
  • alterar formato de erro;
  • aumentar versão mínima do Node.js quando consumidores antigos deixam de funcionar;
  • mudar comportamento padrão incompatível.

Versões 0.x

A especificação permite tratar 0.y.z como desenvolvimento inicial. Na prática, consumidores ainda esperam uma política clara. Muitos projetos usam:

  • patch para correções;
  • minor para mudanças incompatíveis antes de 1.0.

Documente a regra. Se o pacote é usado em produção e possui API estável, considere publicar 1.0.0.

Pré-releases

2.0.0-alpha.1
2.0.0-beta.2
2.0.0-rc.1

Identificadores após hífen possuem precedência menor que a versão final. Use para testes antecipados sem colocar a versão em latest.

Build metadata

1.4.0+build.20260723

Conteúdo após + não altera precedência SemVer. O registry e ferramentas podem ter regras próprias; não dependa disso como sistema principal de release.

Ranges exatos

"dependency": "1.2.3"

Instala somente a versão exata, embora o lockfile já fixe a resolução concreta. Use quando atualização automática é arriscada ou em ferramentas sensíveis.

Caret

"dependency": "^1.2.3"

Para versões 1.x, aceita atualizações menores e patches sem chegar a 2.0.0. Em 0.x, o comportamento é mais restrito porque o primeiro componente não zero define a compatibilidade.

Tilde

"dependency": "~1.2.3"

Aceita patches dentro de 1.2.x, sem chegar a 1.3.0.

Wildcards

1.2.x
1.x
*

Ranges amplos aumentam a superfície de mudança. Evite * em dependências de produção.

Intervalos

>=1.2.0 <2.0.0

Intervalos explícitos são úteis em peerDependencies, desde que realmente testados.

Lockfile e ranges

O range declara o que é aceitável; o package-lock.json registra o que foi instalado. Em aplicações:

npm ci

Use dependências atualizadas por pull requests controlados. Consulte Segurança de Dependências no Node.js.

dependencies e devDependencies

Bibliotecas necessárias em runtime ficam em dependencies. Ferramentas de build e teste ficam em devDependencies. Classificação errada pode aumentar pacote ou quebrar instalação.

peerDependencies

{
  "peerDependencies": {
    "fastify": "^5.0.0"
  }
}

Peer dependency comunica que o consumidor fornece a dependência. Declare somente versões testadas e evite ranges estreitos sem motivo.

peerDependenciesMeta

{
  "peerDependenciesMeta": {
    "fastify": {
      "optional": true
    }
  }
}

Útil para integrações opcionais que o pacote detecta.

engines

{
  "engines": {
    "node": ">=20 <27"
  }
}

Subir o mínimo pode ser breaking, porque consumidores deixam de instalar ou executar. Faça em major, salvo política explicitamente diferente.

Tipos TypeScript

Breaking changes de tipos incluem:

  • tornar propriedade obrigatória;
  • estreitar parâmetro;
  • ampliar união usada em switch exaustivo;
  • alterar generic defaults;
  • remover overload;
  • mudar campo readonly;
  • reorganizar exports de tipos.

Compile projetos consumidores de teste para detectar impacto.

Erros e contratos

Se consumidores verificam error.code, remover ou renomear o código é breaking. Mensagens humanas deveriam ser consideradas instáveis, mas documente essa política.

SemVer em APIs HTTP

A versão do pacote npm e a versão da API HTTP são contratos diferentes. Um deploy interno pode mudar pacote sem alterar endpoint. Veja Versionamento de API no Node.js.

Comando npm version

npm version patch
npm version minor
npm version major

O comando atualiza package.json, lockfile e pode criar commit e tag, dependendo da configuração.

Pré-release com npm version

npm version prerelease --preid=beta

Produz algo como 2.0.0-beta.0.

Dist-tags

O npm usa tags como:

  • latest;
  • next;
  • beta;
  • legacy.
npm publish --tag next

Pré-releases não devem substituir latest acidentalmente.

Changelog

Cada release deve explicar:

  • novidades;
  • correções;
  • breaking changes;
  • migração;
  • depreciações;
  • requisitos de runtime.

Depreciação antes da remoção

Uma migração saudável:

  1. adicione a nova API em minor;
  2. marque a antiga como deprecated;
  3. documente alternativa;
  4. mantenha por período definido;
  5. remova em major.

Testes de compatibilidade

Além dos testes unitários:

  • instale o tarball em projeto exemplo;
  • teste ESM e CommonJS quando suportados;
  • compile TypeScript consumidor;
  • execute versões mínimas do Node.js;
  • verifique exports;
  • compare API pública.

Use Contract Testing com Pact para contratos entre serviços; para pacotes, mantenha fixtures consumidoras.

Monorepos

Escolha versionamento:

  • fixed: todos os pacotes sobem juntos;
  • independent: somente pacotes afetados mudam.

Veja npm Workspaces no Node.js.

Automação

Changesets e semantic-release podem calcular versões, changelog e publicação. A automação não substitui a decisão sobre compatibilidade; commits e arquivos de changeset precisam classificar a alteração corretamente.

Erros comuns

  • Feature em patch: consumidores recebem mudança inesperada.
  • Breaking em minor: range caret instala quebra.
  • Major sem guia: migração vira tentativa e erro.
  • Tipos ignorados: runtime compatível, compilação quebra.
  • Latest em beta: todos recebem pré-release.
  • Range amplo não testado: peer incompatível.
  • Sem API pública: SemVer vira opinião.
  • Versão alterada manualmente sem lockfile: estado diverge.

Checklist de release

  • Classificar patch, minor ou major.
  • Atualizar changelog.
  • Executar lint, typecheck, testes e build.
  • Testar tarball.
  • Validar versões do Node.js.
  • Revisar exports e tipos.
  • Confirmar dist-tag.
  • Publicar com autenticação segura.
  • Criar tag e release.
  • Monitorar consumidores.

Conclusão

O Semantic Versioning no Node.js comunica risco e compatibilidade. Patch corrige, minor adiciona de forma compatível e major altera o contrato.

Defina a API pública, considere tipos e comportamento, teste o pacote empacotado e documente migrações. Quando ranges, lockfile, dist-tags e automação são usados com disciplina, SemVer permite atualizar dependências com confiança sem esconder breaking changes.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita