Versionado semántico El sistema de numeración que depende tu npm install
Los tres números de Semver son un contrato. LAS MAYORES rompen, LAS MENORES añaden, LAS PATCH corriguen — y cuando tu compilación falla tras ejecutar npm install, en nueve de cada diez casos alguien ignoró ese contrato. A continuación se explica cómo funciona el sistema de numeración, qué hace realmente ^ y ~ en package.json, y por qué es indispensable comprometer tu archivo de bloqueo.
Tu compilación falló. Funcionaba el viernes. npm install el lunes se incorporó react-query@5 y ahora la mitad de tus hooks han desaparecido. Estás mirando una pila de errores que no existía antes, y en algún lugar un cambio de versión está acumulando polvo.
Esta es una historia de semver. Específicamente, es tu culpa.
Qué significan realmente los tres números
MAJOR.MINOR.PATCH — eso es todo. Tres espacios, tres reglas:
- PATCH (1.2.3 → 1.2.4): Corrección de errores. Nada en tu código necesita cambiar. Solo obtienes un comportamiento menos defectuoso.
- MINOR (1.2.3 → 1.3.0): Se añadió una nueva característica, compatible hacia atrás. No tienes que usarla, pero está disponible.
- MAJOR (1.2.3 → 2.0.0): Algo falló. Una función fue renombrada, eliminada o cambió su firma. La API anterior desapareció o funciona de forma diferente.
La palabra clave en los tres es compatible hacia atrás. MINOR y PATCH son promesas: “no rompimos nada que ya estabas usando”. MAJOR es una advertencia: “sí lo hicimos”.
Cuando un mantenedor aumenta MAJOR y no lo notaste porque estabas pinado ^1.0.0 en package.json y el archivo de bloqueo era obsoleto — eso es tu culpa. El estándar funcionó exactamente como estaba diseñado.
El contrato social de semver
Semver es una convención, no una ley. Los paquetes pueden afirmar que siguen esta convención y luego lanzar una MINOR con cambios que rompen. Cuando eso ocurre, es una falta de fidelidad por parte del mantenedor. Pero cuando un paquete aumenta correctamente MAJOR para indicar un cambio que rompe y tú lo incorporas sin revisar — tú eres quien rompió tu propia compilación.
Esta es la razón por la que existen los cambios de versión. Una CHANGELOG.md entrada que dice “Eliminado lo desactualizado v1Api — use v2Api en su lugar” es el mantenedor cumpliendo con su parte. No leerlo es tú ignorando tu parte. El cambio de versión es una lectura de dos minutos. La sesión de depuración que evita es mucho más larga.
^ vs ~ — las mecánicas reales
En package.json, ^ (caret) y ~ (tilde) definen rangos de versiones. Aparentemente parecen similares y comportan de forma muy diferente.
Caret (^): Permite cualquier versión que no aumente MAJOR. Esto es la configuración predeterminada de npm cuando ejecutas npm install some-package.
^1.2.3se resuelve a>=1.2.3 <2.0.0^0.2.3se resuelve a>=0.2.3 <0.3.0— caso especial:0.xconsidera a MINOR como rompedora^0.0.3se resuelve a>=0.0.3 <0.0.4—0.0.xfija exactamente, sin margen de maniobra
Tilde (~): Permite solo actualizaciones de PATCH, dentro del MINOR especificado.
~1.2.3se resuelve a>=1.2.3 <1.3.0~1.2se resuelve a>=1.2.0 <1.3.0— igual que~1.2.0~1se resuelve a>=1.0.0 <2.0.0— equivalente a^1.0.0en este momento
Ejemplos de rangos de versiones
| Rango | Qué permite | Coincidencias concretas |
|---|---|---|
1.2.3 | Exactamente esta versión | Solo 1.2.3 |
^1.2.3 | Cualquier MINOR/PATCH ≥ 1.2.3 | 1.2.4, 1.3.0, 1.99.0 — NO 2.0.0 |
^0.2.3 | PATCH dentro de 0.2.x solo | 0.2.4, 0.2.99 — NO 0.3.0 |
~1.2.3 | PATCH dentro de 1.2.x solo | 1.2.4, 1.2.99 — NO 1.3.0 |
~1.2 | Cualquier parche de 1.2.x | 1.2.0, 1.2.1, 1.2.99 |
>=1.2.3 <2.0.0 | Rango explícito | Resultado igual que ^1.2.3 |
1.2.x | Cualquier parche de 1.2 | 1.2.0, 1.2.1, 1.2.99 |
* | Cualquier cosa | Lo que npm sienta que debe instalar hoy |
El * El rango es una estrategia de “confía en mí, amigo” de versionado. Estás pines nada. Si un paquete lanza una API completamente reescrita, lo recibirás en la próxima v9.0.0 con caché limpio. Usa este rango solo en aplicaciones de nivel superior que nunca son dependencias de otros paquetes — y siquiera entonces, solo si la reproducibilidad realmente no importa para ti (sí lo importa). npm install con un caché limpio. Úsalo solo en aplicaciones de nivel superior que no sean dependencias de otros paquetes — y incluso entonces, solo si la reproducibilidad realmente no importa para usted (sí lo hace).
Identificadores de versión preliminar
Antes de una versión estable, los mantenedores etiquetan las versiones con una etiqueta de versión preliminar:
1.0.0-alpha.1— temprana, inestable, la API probablemente aún está cambiando1.0.0-beta.2— completa en funcionalidad, aún en prueba, espera algunos bordes irregulares1.0.0-rc.1— candidato a lanzamiento, debería estar listo para producción a menos que algo salga en la prueba final
Las versiones preliminares se ordenan debajo la versión estable: 1.0.0-alpha.1 < 1.0.0. Y críticamente, ^1.0.0 hará no instalar 2.0.0-beta.1 — las versiones preliminares solo coinciden si las especificas explícitamente en tu rango. Este comportamiento es el que te evita elegir accidentalmente una versión alpha cuando querías seguir las versiones estables.
Si estás consumiendo un paquete que solo tiene versiones preliminares, fija la cadena de versión completa: "some-package": "1.0.0-beta.2". No uses ^ o ~ con versiones preliminares a menos que sepas que el mantenedor las trata con cuidado — la mayoría no lo hacen.
Verificar un rango antes de comprometerlo
Antes de fijar un rango de versión en package.json, vale la pena confirmar qué estás realmente aceptando instalar. El Calculador de versiones semánticas recibe un rango de versión y una lista de versiones candidatas y te muestra cuáles coinciden — útil cuando estás incierto si ~2.3 incluye una versión específica que necesitas, o cuando estás revisando una solicitud de cambios y el rango parece incorrecto.
Los tres modos de falla
La mayoría de los fallos relacionados con semver en compilaciones siguen uno de estos tres patrones:
^+ Aumento de MAJOR + archivo de bloqueo eliminado: Estabas pinado^1.0.0, el mantenedor lanzó2.0.0, el archivo de bloqueo fue eliminado o nunca se cometió, el CI instala 2.0.0. Solución: comite tu archivo de bloqueo. En todos los proyectos. Sin excepciones.*en una biblioteca que publicas: Eres autor de una biblioteca que usó*para una dependencia. Cada usuario descendente de tu paquete hereda tu rango genérico. Has convertido su grafo de dependencias en tu problema. Solución: usa rangos explícitos en cualquier cosa que publiques en npm.- Versión preliminar sin archivo de bloqueo: Un rango suelto incorporó
1.0.0-alpha.3, la API cambió dealpha.1, nada funciona. Solución: fija explícitamente las versiones preliminares y — digámoslo juntos — comite el archivo de bloqueo.
Lee el cambio de versión
Cuando se lanza una versión MAJOR en cualquier parte de tu árbol de dependencias, dedica dos minutos al cambio de versión. Los mantenedores lo escribieron para que no tuvieras que deducir el fallo desde una pila de errores a las 3 de la madrugada.
Si un paquete lanza cambios que rompen bajo un aumento de MINOR sin un cambio de versión — eso es falta de fidelidad. Abre un issue. Llama la atención públicamente. Pero si el aumento MAJOR era claramente visible, la guía de migración era detallada y tú lo incorporaste sin revisar: la herramienta hizo exactamente lo que te pediste. El contrato estaba escrito en tres números. Solo no lo leíste.
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta was added on Jun 26, 2026
