O que o ^ do package.json realmente permite
Está em todas as linhas de dependências de todos os projetos, e é frequentemente lido como decoração. Não é: é um contrato sobre o que pode entrar no seu projeto sem ninguém dar por isso.
1. Os três números
3 . 4 . 2
│ │ └── PATCH: correções, sem mudar comportamento
│ └────── MINOR: funcionalidades novas, compatíveis
└────────── MAJOR: mudanças que partem código existente2. O que cada símbolo deixa passar
{
"dependencies": {
"biblioteca-a": "^3.4.2",
"biblioteca-b": "~3.4.2",
"biblioteca-c": "3.4.2"
}
}^3.4.2— aceita até menos de4.0.0. Entram funcionalidades novas.~3.4.2— aceita até menos de3.5.0. Só correções.3.4.2— exatamente esta.
3. A exceção que apanha toda a gente
Antes da versão 1.0.0, as regras mudam: uma biblioteca em 0.x não promete nada, e o npm sabe disso.
^0.4.2 aceita até menos de 0.5.0 (comporta-se como o ~)
^0.0.2 aceita apenas 0.0.2 (não aceita mais nada)É por isso que uma dependência em 0.x pode partir tudo numa atualização de minor — e continuar a cumprir a especificação à letra.
4. Quem manda, no fim, é o lockfile
O package.json diz o que é permitido. O package-lock.json diz o que está instalado, até à última dependência de dependência. É por isso que o lockfile se comita, e é por isso que num servidor se usa npm ci e não npm install: o primeiro instala o lockfile tal e qual, o segundo tem licença para subir dentro dos intervalos.
5. Ver antes de subir
# O que está para trás, sem mexer em nada
npm outdated
# Subir dentro do que os símbolos permitem
npm update
# Passar a major: é uma decisão, e lê-se o changelog antes
npm install biblioteca-a@4Uma nota final sobre confiança: a especificação é uma promessa, não uma garantia. Há projetos que partem compatibilidade num patch sem querer. É para esses dias que existe o lockfile e uma bateria de testes que corre antes de publicar.