Calculadora SemVer

Comparar y calcular versiones semánticas

Entendiendo Sintaxis de Rangos SemVer
TL;DR

La sintaxis de rangos SemVer (^, ~, >=, ||) permite a los gestores de paquetes resolver versiones compatibles. Comprenderla previene cambios incompatibles inesperados.

¿Qué son los rangos SemVer?

Mientras que el Versionado Semántico define cómo numerar las versiones, la sintaxis de rangos SemVer define cómo expresar qué versiones son aceptables como dependencias. La sintaxis de rangos es el lenguaje que los gestores de paquetes como npm, Yarn, Cargo y Composer utilizan para determinar qué versiones de una dependencia son compatibles con tu proyecto.

Cuando escribes "lodash": "^4.17.21" en tu package.json, estás declarando un rango: “cualquier versión de lodash que sea mayor o igual a 4.17.21 y menor que 5.0.0.” El gestor de paquetes usa este rango para seleccionar la mejor versión coincidente del registro, equilibrando entre obtener las últimas correcciones de errores y evitar cambios incompatibles.

Comprender la sintaxis de rangos es esencial para cualquier desarrollador que gestione dependencias. Los rangos mal configurados son una fuente común de errores del tipo “funciona en mi máquina”, compilaciones rotas y problemas inesperados en producción.

Caret (^) vs Tilde (~)

Los dos operadores de rango más utilizados son el caret (^) y el tilde (~). Son los predeterminados en la mayoría de los gestores de paquetes, y su comportamiento difiere de una manera crítica.

Caret (^) — Compatible con la versión

El caret permite cambios que no modifican el dígito más a la izquierda distinto de cero:

RangoEquivalentePermite
^1.2.3>=1.2.3 <2.0.0Actualizaciones menores y de parche
^0.2.3>=0.2.3 <0.3.0Solo actualizaciones de parche
^0.0.3>=0.0.3 <0.0.4Nada (coincidencia exacta)

El caret es el operador predeterminado en npm. Cuando ejecutas npm install lodash, la versión guardada en package.json usa el prefijo caret (por ejemplo, ^4.17.21). Para versiones 1.0.0 y superiores, esto es generalmente seguro porque SemVer garantiza compatibilidad retroactiva dentro de la misma versión MAJOR.

Sin embargo, para versiones 0.x, el caret se vuelve mucho más restrictivo. ^0.2.3 solo permite actualizaciones de parche porque la versión MINOR es el dígito más a la izquierda distinto de cero. Esto protege contra la inestabilidad que SemVer permite durante el desarrollo inicial.

Tilde (~) — Aproximadamente equivalente

El tilde solo permite cambios a nivel de parche si se especifica una versión MINOR:

RangoEquivalentePermite
~1.2.3>=1.2.3 <1.3.0Solo actualizaciones de parche
~1.2>=1.2.0 <1.3.0Solo actualizaciones de parche
~1>=1.0.0 <2.0.0Actualizaciones menores y de parche

El tilde es más restrictivo que el caret para versiones >= 1.0.0. Mientras que ^1.2.3 aceptaría 1.9.0, ~1.2.3 no lo haría — se limita hasta la siguiente versión MINOR.

Caret vs Tilde Range Comparison A number line diagram showing that ^1.2.3 includes versions from 1.2.3 up to but not including 2.0.0, while ~1.2.3 includes only versions from 1.2.3 up to but not including 1.3.0. Range Comparison: ^1.2.3 vs ~1.2.3 1.0.0 1.2.3 1.3.0 1.5.0 1.9.0 2.0.0 ^1.2.3 = >=1.2.3 <2.0.0 ~1.2.3 ~1.2.3 = >=1.2.3 <1.3.0 Caret — allows minor + patch updates Tilde — allows patch updates only Dashed line = excluded boundary (upper bound is exclusive)

Operadores de comparación

Además del caret y el tilde, la sintaxis de rangos SemVer admite operadores de comparación explícitos que te dan control detallado:

OperadorSignificadoEjemploSe resuelve como
>=Mayor o igual que>=1.2.31.2.3 en adelante (sin límite superior)
>Mayor que>1.2.3Superior a 1.2.3, sin incluirla
<=Menor o igual que<=2.0.02.0.0 e inferiores
<Menor que<2.0.0Inferior a 2.0.0, sin incluirla
=Coincidencia exacta=1.2.3Solo 1.2.3

Puedes combinar operadores para definir rangos precisos:

>=1.2.3 <2.0.0     # Equivalente a ^1.2.3
>=1.0.0 <1.3.0     # 1.0.0 hasta 1.2.x

Rangos con guión

Un guión entre dos versiones define un rango inclusivo:

1.2.3 - 2.3.4     # >=1.2.3 <=2.3.4
1.2 - 2.3.4       # >=1.2.0 <=2.3.4
1.2.3 - 2.3       # >=1.2.3 <2.4.0

Cuando se usa una versión parcial en el lado derecho, los componentes faltantes se tratan como comodines hasta el siguiente límite significativo. 1.2.3 - 2.3 significa “hasta pero sin incluir 2.4.0.”

X-Ranges y comodines

Cualquiera de los tres componentes de versión puede reemplazarse con x, X o * para indicar “cualquier valor”:

RangoEquivalenteDescripción
*>=0.0.0Cualquier versión
1.x>=1.0.0 <2.0.0Cualquier versión 1.x.x
1.2.x>=1.2.0 <1.3.0Cualquier versión 1.2.x
"" (vacío)>=0.0.0Igual que *

Los X-ranges son útiles para expresar la intención con claridad: 1.x dice “dependo de la API v1” sin especificar qué versión menor o de parche.

Combinar rangos con OR (||)

El operador doble pipe (||) combina múltiples rangos. Una versión satisface el rango combinado si coincide con cualquiera de los sub-rangos:

^1.2.3 || ^2.0.0          # 1.x (>=1.2.3) O 2.x
>=1.0.0 <1.5.0 || >=2.0.0 # 1.0-1.4.x O 2.0+

Esto es útil cuando una librería soporta múltiples versiones mayores de una dependencia de pares. Por ejemplo, una librería de componentes React podría declarar "react": "^17.0.0 || ^18.0.0" para soportar tanto React 17 como React 18.

Tabla de referencia de rangos SemVer

SintaxisEquivalente¿Predeterminado en npm?Caso de uso
^1.2.3>=1.2.3 <2.0.0Sí (predeterminado)Aceptar actualizaciones menores + parche
~1.2.3>=1.2.3 <1.3.0NoAceptar solo actualizaciones de parche
1.2.3=1.2.3NoVersión exacta (fijada)
>=1.0.0 <2.0.0IgualNoRango explícito
1.2.x>=1.2.0 <1.3.0NoComodín de parche
*>=0.0.0NoCualquier versión
^1.2.3 || ^2.0.0UniónNoMúltiples versiones mayores

Casos de uso comunes

  • Dependencias npm / Yarn: El campo dependencies de package.json usa rangos SemVer para declarar versiones de dependencias aceptables. El caret (^) es el operador predeterminado.
  • Dependencias de pares: Las librerías declaran dependencias de pares con rangos para soportar múltiples versiones mayores de frameworks (por ejemplo, "react": "^17.0.0 || ^18.0.0").
  • Restricciones en CI/CD: Los pipelines de compilación usan rangos para especificar versiones de herramientas, asegurando compilaciones consistentes mientras reciben actualizaciones de parche.
  • Lockfiles: package-lock.json y yarn.lock congelan las versiones exactas resueltas, mientras que los rangos en package.json definen el espacio de versiones aceptable.
  • Protocolos de workspace en monorepos: Las herramientas de monorepo (Turborepo, Lerna, pnpm) usan rangos SemVer para gestionar dependencias entre paquetes dentro del workspace.
  • Imágenes de contenedores: Las directivas FROM en Dockerfile usan etiquetas de versión que siguen las convenciones SemVer (por ejemplo, node:18.17 para el último parche 18.17.x).

Prueba estos ejemplos

Comparar dos versiones Válido

Compara la version 1.4.2 con 2.0.0. La herramienta detecta una diferencia de version MAJOR, lo que significa que se introdujeron cambios incompatibles.

1.4.2
Rango caret — Satisface Válido

Verifica si la version 1.9.0 satisface el rango caret ^1.2.3 (se resuelve como >=1.2.3 <2.0.0). Resultado: satisface.

1.9.0
Rango tilde — NO satisface Válido

Verifica si la version 1.3.0 satisface el rango tilde ~1.2.3 (se resuelve como >=1.2.3 <1.3.0). Resultado: no satisface, porque el tilde solo permite actualizaciones de parche.

1.3.0
Incrementar version menor Válido

Incrementa la version 1.4.2 con un bump menor, produciendo 1.5.0. El numero de parche se reinicia a cero.

1.4.2