Muito provavelmente, você já precisou instalar uma biblioteca para utilizar em
seu projeto e, ao fazer isso, deve ter percebido que ela vem com um
número de versão. Esse número pode aparecer no nome do arquivo que
você está referenciando no src
da tag script
ou dentro de um arquivo
package.json
, por exemplo. Esse número nos ajuda em diversas coisas: a achar a
documentação correta para a versão que estamos utilizando, a saber se estamos na
mais atual, etc. Mas o mais importante é que ele nos ajuda a entender o que
mudou entre uma versão e outra. E é aí que o semantic versioning entra.
O que é o versionamento semântico?
O versionamento semântico (semantic versioning em inglês), ou SemVer, é uma convenção de versionamento utilizada para definir como as versões de um software devem ser incrementadas.
Essa convenção é baseada em três números, separados por pontos, que
representam, respectivamente, a versão major (1.),
minor (2.) e patch (3). Exemplo: 1.2.3
.
Patch
O número do patch é incrementado quando correções de bugs são feitas na biblioteca. Ou seja, quando a mudança não adiciona novas funcionalidades e não quebra a compatibilidade com a versão anterior; o que funcionava antes continua funcionando.
Exemplo:
Quando a versão do React DOM foi atualizada de 17.0.0
para 17.0.1
:
17.0.1 (October 22, 2020)
React DOM
Fix a crash in IE11. (@gaearon in #20071)
trecho do changelog do react
Podemos ver, através de um trecho do changelog do React
, que a versão 17.0.1
foi lançada para corrigir um bug que estava causando um
crash no Internet Explorer 11 (RIP).
Minor
O número minor é incrementado quando novas funcionalidades são adicionadas à biblioteca. Essas novas funcionalidades não devem afetar o funcionamento do que já existia, ou seja, não devem quebrar a compatibilidade com a versão anterior.
Durante a publicação dessa nova versão, o número do patch é resetado para
0
.
Um ponto importante é que, durante a publicação de uma nova versão minor,
também é possível que correções de bugs sejam incluídas. Mas mesmo que isso
aconteça, devemos manter o reset do patch para o número 0
.
Exemplo:
Podemos pegar outra biblioteca como exemplo, o Jest
. Quando a versão foi
atualizada de 29.6.4
para 29.7.0
, vemos que novas funcionalidades
adicionadas, mas também houve correções de bugs.
29.7.0
Features
[create-jest]
Addnpm init
/yarn create
initialiser for Jest projects (#14453)
[jest-validate]
Allow deprecation warnings for unknown options (#14499)Fixes
[jest-resolver]
Replace unmatched capture groups inmoduleNameMapper
with empty string instead ofundefined
(#14507)
[jest-snapshot]
Allow for strings as well as template literals in inline snapshots (#14465)
[@jest/test-sequencer]
Calculate test runtime ifperStats.duration
is missing (#14473)
trecho do changelog do jest
Não vamos nos apegar ao o que mudou, mas podemos ver que a versão 29.7.0
foi
lançada com novas funcionalidades e também com bug fixes, ela
avançou de 29.6.4
para 29.7.0
. Se somente as correções de bugs fossem
incluídas, a versão seria 29.6.5
, pois somente o patch deveria ser
incrementado.
Major
O número major é incrementado quando mudanças que quebram a compatibilidade com a versão anterior são feitas. Ou seja, quando mudanças que afetam a forma como a biblioteca é utilizada são realizadas e, com isso o desenvolvedor que utiliza a biblioteca precisa fazer alterações em seu código para que ele continue funcionando. Essas mudanças são conhecidas como breaking-changes.
Resumindo, mudanças que quebram a compatibilidade com a versão anterior são mudanças que fazem com que o código que funcionava antes não funcione mais com a nova versão.
Quando isso acontece o mantenedor da biblioteca deve incrementar o número
major e resetar os números minor e patch para 0
.
Assim como na minor, é possível que novas funcionalidades e correções de bugs
sejam incluídas em uma nova versão major, mas mesmo que isso aconteça, devemos
manter o reset dos números minor e patch para 0
.
Guia de migração
É bem comum que os desenvolvedores das bibliotecas forneçam um guia de migração para ajudar os usuários a migrarem de uma versão para outra. Bibliotecas como o React, Next.js e Jest, por exemplo, possuem guias de migração bem detalhados:
Changelogs
Além do guia de migração, também existe um tal de "changelog", que é um documento que lista todas as mudanças feitas em uma biblioteca/aplicação, desde a primeira versão até a atual.
Com esse arquivo, conseguimos atualizar a versão da biblioteca mesmo que ela não forneça um guia de migração, pois, se bem escrito, ele deve conter todas as mudanças e, principalmente, todas as breaking-changes que ocorreram.
Também podemos encontrar esse tipo de informação dentro das releases no repositório da biblioteca, como, por exemplo, no repositório do React
Exemplo na prática:
Aqui teremos uma simulação de biblioteca que provém funções matemáticas básicas e que segue o SemVer.
export function sum(a, b) { return a + b; } // temos um bug aqui, a subtração está somando export function subtract(a, b) { return a + b; }
No exemplo acima, temos uma simulação de lib onde, a cada nova versão, o número de versão é incrementado seguindo o semantic versioning.
Além disso, temos um arquivo CHANGELOG.md
que lista todas as mudanças feitas
em cada versão, desde a primeira até a última.
Versões 0.y.z
Uma biblioteca com versão 0.3.0
, por exemplo, indica que ela ainda está em fase
de desenvolvimento, isso significa que ela pode ter breaking changes a
qualquer momento, e essas breaking changes não irão incrementar o número
major.
O desenvolvedor da biblioteca deve seguir o SemVer a partir da versão 1.0.0
.
A versão 1.0.0
deve ser lançada quando a biblioteca estiver pronta para ser
utilizada em produção e sua API (métodos/funções/classes que ela disponibiliza
) estiver estável.
Um grande exemplo disso é o React Native, que está por aí há anos e ainda continua em uma versão de desenvolvimento. Quem já precisou atualizar a versão do React Native sabe o trabalho que isso pode causar com tantas breaking changes possíveis 🙁
Portanto, tenha cuidado a atualizar as dependências do seu projeto que estão em versões de desenvolvimento (0.y.z), pois podem ocorrer inconsistências. Sempre leia o changelog e procure por guias de migração na documentação da biblioteca.
Ponto importante:
Caso você venha a desenvolver uma biblioteca, tome cuidado ao utilizar ferramentas como o semantic-release, lerna, para gerenciar o release da primeira versão
1.0.0
. Caso sua biblioteca esteja em alguma versão0.x.y
, essas ferramentas podem não modificar a versão para a primeira major1.0.0
, mesmo que você informe a elas que ocorreram breaking changes, pois elas seguem o semantic version e não irão incrementar o major enquanto a versão for0.x.y
.
Prereleases
Além das versões 0.y.z
, também temos as prereleases, que são versões
lançadas antes da versão final proposta, para testes e feedbacks da comunidade.
Essas versões são identificadas por um sufixo, como 1.0.0-alpha.1
,
1.0.0-beta.1
, 1.0.0-rc.1
, etc. Quando os testes são finalizados e a versão
estiver pronta para ser lançada, a versão final será lançada sem o sufixo.
Podemos ver que o Next.js utiliza bastante as versões prereleases para testar novas funcionalidades antes de lançar a versão final.
Tais sufixos não seguem nenhuma regra específica, ficando a cargo do mantenedor
da biblioteca decidir como irá nomear essas versões. Porém é comum vermos
alpha
, beta
, next
, rc
e canary
sendo utilizados.
Elas não são instaladas por padrão ao utilizar o comando npm install
, sendo
necessário informar o sufixo para instalar uma versão prerelease.
Exemplo:
npm install [email protected]
E para terminar, vale mencionar que o SemVer é uma convenção e não uma regra. Portanto, é possível que algumas bibliotecas não sigam essa convenção, mas é importante que o desenvolvedor da biblioteca informe isso em sua documentação.
Por fim, quem criou o SemVer foi Tom Preston-Werner e sua documentação pode ser encontrada em semver.org
Comentários 0