12k
All articles

Versionamento Semântico Explicado

SemVer no npm explicado: MAJOR.MINOR.PATCH, intervalos caret e tilde, versões 0.x, pré-lançamentos e lock files para atualizações seguras.

OpenReplay Team
OpenReplay Team
Versionamento Semântico Explicado

Se você já abriu um arquivo package.json e se perguntou por que uma dependência mostra ^1.4.2 enquanto outra mostra ~2.0.1, você já está lidando com as consequências práticas do Versionamento Semântico. Entender como o SemVer funciona ajuda você a tomar melhores decisões sobre atualizações de dependências, evitar builds quebrados e comunicar mudanças com clareza quando publicar seus próprios pacotes.

Pontos-Chave

  • O SemVer usa o formato MAJOR.MINOR.PATCH, onde cada segmento sinaliza um tipo específico de mudança: incompatível, aditiva ou corretiva.
  • Os operadores de intervalo do npm (^, ~ e versões exatas) controlam como as dependências são atualizadas, sendo o caret o padrão e o mais permissivo dentro de uma versão major.
  • Arquivos de lock como package-lock.json garantem instalações reproduzíveis entre equipes e ambientes de CI, independentemente do intervalo especificado.
  • Versões abaixo de 1.0.0 são consideradas instáveis, e tags de pré-lançamento (por exemplo, 1.0.0-beta.1) são tratadas como releases explicitamente instáveis que o npm não instalará por meio de intervalos normais, a menos que solicitado.
  • O SemVer é um contrato social entre mantenedores e consumidores, não um mecanismo de imposição técnica.

O que é Versionamento Semântico?

Versionamento Semântico (SemVer) é uma especificação de versionamento que atribui significado aos números de versão. Uma versão SemVer assume a forma MAJOR.MINOR.PATCH, onde cada número sinaliza um tipo específico de mudança:

  • MAJOR — uma mudança incompatível com a API pública anterior
  • MINOR — nova funcionalidade adicionada de forma retrocompatível
  • PATCH — uma correção de bug retrocompatível

Quando um pacote passa de 2.6.9 para 3.0.0, algo quebrou a retrocompatibilidade. Uma mudança de 2.6.9 para 2.7.0 adiciona recursos sem quebrar nada. Uma mudança para 2.6.10 corrige um bug.

Um esclarecimento importante: o SemVer só funciona de maneira significativa quando um pacote tem uma API pública definida. Sem um contrato claro entre o pacote e seus consumidores, o número da versão é apenas um número.

Como o npm Usa o SemVer para Intervalos de Dependência

O versionamento do npm é construído diretamente sobre o SemVer, mas a sintaxe de intervalo no package.json é uma camada acima dele — não o SemVer em si.

"dependencies": {
  "lodash": "^4.17.21",
  "axios": "~1.6.0",
  "react": "18.2.0"
}

Aqui está o que cada operador de intervalo significa:

  • ^ (caret) — permite atualizações MINOR e PATCH, mas não MAJOR. ^4.17.21 aceita qualquer versão a partir de 4.17.21 até, mas não incluindo, 5.0.0. Para releases 0.x, os intervalos com caret são mais restritivos: ^0.2.3 permite atualizações abaixo de 0.3.0, e não todas as versões 0.x.
  • ~ (til) — permite atualizações PATCH quando uma versão minor é especificada. ~1.6.0 aceita 1.6.x, mas não 1.7.0.
  • Versão exata — 18.2.0 instala apenas essa versão específica.

O caret é o padrão do npm quando você executa npm install. Ele fornece correções de bugs e novos recursos automaticamente, ao mesmo tempo em que o protege de mudanças incompatíveis — desde que o autor do pacote siga o SemVer corretamente. Essa suposição nem sempre se mantém.

Por que os Arquivos de Lock Importam

Seu package-lock.json registra a versão exata instalada em determinado momento. Mesmo que um intervalo como ^4.17.21 permita versões mais novas, o arquivo de lock fixa o que é realmente usado em sua equipe e ambiente de CI. É por isso que fazer commit do seu arquivo de lock é importante para builds reproduzíveis.

Entendendo Releases 0.x e Versões de Pré-lançamento

Duas áreas frequentemente pegam os desenvolvedores de surpresa:

Releases 0.x são instáveis por definição. Um pacote em 0.4.2 não oferece garantias de compatibilidade. Qualquer coisa pode mudar entre 0.4.2 e 0.5.0. Não confie nas regras de compatibilidade do SemVer para pacotes que ainda não chegaram à 1.0.0.

Versões de pré-lançamento como 1.0.0-beta.1 têm precedência menor que a release estável. O npm não instalará uma versão de pré-lançamento a menos que você a solicite explicitamente. Um intervalo normal como ^1.0.0 não será resolvido automaticamente para 1.1.0-beta.1. Isso protege você de acidentalmente puxar código instável.

Quando Incrementar Qual Versão

Se você mantém um pacote, use isto como guia:

Tipo de mudançaVersão a incrementarExemplo
Mudança incompatível na APIMAJOR1.4.2 → 2.0.0
Novo recurso, retrocompatívelMINOR1.4.2 → 1.5.0
Apenas correção de bugPATCH1.4.2 → 1.4.3
Depreciação de um recurso (sem remoção)MINOR1.4.2 → 1.5.0

Quando incrementar MINOR, redefina PATCH para zero. Quando incrementar MAJOR, redefina tanto MINOR quanto PATCH para zero.

SemVer É um Contrato, Não uma Garantia

O SemVer fornece uma linguagem comum para comunicar mudanças. Mas tecnicamente ele não impede que um mantenedor lance uma mudança incompatível em uma release de patch. Ferramentas como semantic-release podem automatizar o versionamento com base em mensagens de commit, reduzindo erros manuais e ajudando equipes a seguir as convenções do SemVer de forma mais consistente.

Conclusão

Entender o versionamento do npm e o versionamento de pacotes pela lente do SemVer torna você um consumidor mais confiante de pacotes open-source — e um publicador mais responsável dos seus próprios. O formato é simples, mas suas implicações são profundas: cada dígito comunica intenção, cada operador de intervalo molda risco, e cada arquivo de lock protege a reprodutibilidade. Trate o SemVer como o vocabulário compartilhado para o qual foi projetado, e seu gerenciamento de dependências se tornará perceptivelmente mais tranquilo.

Perguntas Frequentes

O que acontece se um autor de pacote não seguir o SemVer corretamente?

Você pode receber mudanças incompatíveis através do que deveria ser uma atualização segura, como um incremento de patch ou minor. Para se proteger, faça commit do seu package-lock.json, revise os changelogs antes de atualizar e considere ferramentas como Renovate ou Dependabot, que apresentam notas de release junto com os incrementos de versão. Para dependências críticas, fixar versões exatas é uma medida defensiva razoável.

Devo usar intervalos com caret ou til no meu package.json?

O caret é o padrão do npm e funciona bem para a maioria das aplicações, pois permite atualizações minor e patch dentro de uma versão major. O til é mais rigoroso, aceitando apenas atualizações de patch, o que se adequa a projetos que priorizam estabilidade em vez de novos recursos. Para bibliotecas que você publica, prefira intervalos com caret para que os consumidores se beneficiem automaticamente de melhorias retrocompatíveis.

Por que o npm trata versões 0.x de forma diferente de versões 1.x e superiores?

A especificação do SemVer afirma explicitamente que qualquer coisa abaixo de 1.0.0 é considerada desenvolvimento inicial, onde a API pública não deve ser considerada estável. Mantenedores podem introduzir mudanças incompatíveis entre quaisquer releases 0.x sem incrementar o número major. Uma vez que um projeto atinge 1.0.0, ele se compromete com as regras completas de compatibilidade do SemVer.

Como instalo uma versão de pré-lançamento como uma beta ou release candidate?

Você deve solicitá-la explicitamente, seja especificando a versão exata (npm install package@1.0.0-beta.1) ou usando uma tag (npm install package@next). Intervalos padrão como ^1.0.0 ignorarão completamente as versões de pré-lançamento, o que evita a instalação acidental de código instável em ambientes de produção.

Open-source session replay

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.