A regra que quase ninguém conhece: ^ em versão 0.x
Todo mundo sabe que ^1.2.3 aceita qualquer coisa até antes da
2.0.0. O que quase ninguém sabe é que
o ^ muda de comportamento abaixo da 1.0:
| Faixa | Significa | O que trava |
|---|---|---|
^1.2.3 | >=1.2.3 <2.0.0 | o major |
^0.2.3 | >=0.2.3 <0.3.0 | o minor |
^0.0.3 | >=0.0.3 <0.0.4 | o patch — só essa versão |
A lógica é boa: antes da 1.0 a biblioteca ainda está se achando, e o autor
quebra coisa entre versões menores. O semver reconhece isso e o
^ fica mais conservador sozinho.
A consequência prática é grande. Num projeto cheio de dependências
0.x — comum em ecossistema novo —
npm update não traz quase nada, e as pessoas
acham que a ferramenta está quebrada. Não está: o ^ é que está
travando o minor.
^ ou ~: qual usar
~ é mais apertado: aceita só correções dentro do mesmo minor.
^ aceita também os minors novos.
~1.2.3 → >=1.2.3 <1.3.0 só patch
^1.2.3 → >=1.2.3 <2.0.0 patch e minor
Na prática: use ^, que é o padrão do npm.
Ele confia no semver — minor não deve quebrar nada — e é o que permite
receber correção de segurança sem esforço. Descer para ~ é
para dependência que já te traiu, e fixar exato é para quando você tem
motivo específico.
package.json que só é atualizado na marra, uma vez por ano.
Quem garante build reproduzível é o lockfile, não o
package.json.
O lockfile é que manda
Ponto que confunde muita gente: a faixa no package.json diz o
que é aceitável; o package-lock.json diz o que está
instalado. Com o lockfile commitado, todo mundo instala exatamente
a mesma versão — mesmo com ^ em tudo.
A faixa só volta a ser consultada quando você roda npm update,
instala um pacote novo, ou quando não existe lockfile.
npm ci # instala EXATAMENTE o lockfile; ignora a faixa
npm install # respeita a faixa e pode atualizar o lockfile
npm update # sobe até o topo do que a faixa permite
Pré-lançamento não entra sozinho
Esta pega no CI e assusta: ^1.2.3
não aceita 2.0.0-beta.1 — nem
1.5.0-rc.1. Versões de pré-lançamento ficam de fora de
qualquer faixa, a menos que a própria faixa cite um pré-lançamento com o
mesmo major.minor.patch.
^1.2.3 não aceita 1.5.0-rc.1
>=1.2.3-beta.1 aceita 1.2.3-beta.2, mas não 1.5.0-rc.1
É proteção deliberada: você não quer que um npm update puxe
uma beta para produção sem você pedir.
Os outros formatos que você vai encontrar
| Escrito assim | Quer dizer |
|---|---|
1.2.3 | exatamente essa versão |
1.2.x ou 1.2 | >=1.2.0 <1.3.0 |
1.x ou 1 | >=1.0.0 <2.0.0 |
* ou vazio | qualquer versão — evite |
1.2.3 - 2.3.4 | de uma até a outra, incluindo as duas |
>=1.2.3 <2.0.0 | as duas condições ao mesmo tempo |
^1 || ^2 | uma OU outra |
Se a faixa está causando conflito na instalação, o
diagnóstico de erro do npm lê o
bloco do ERESOLVE e diz qual pacote briga com qual.