Versionado semántico (semver): el sistema que evita breaking changes

Entiende cómo funciona semver y por qué ^, ~ y los rangos de versiones son cruciales. Aprende a evitar breaking changes accidentales y a actualizar dependencias de forma segura.

El versionado semántico (semver) es el sistema que permite a millones de paquetes JavaScript coexistir sin romperse mutuamente. Cuando ves ^4.17.21 o ~1.0.0, estás viendo semver en acción. Entender este sistema te protege de actualizaciones que rompen tu código.

En esta lección vas a dominar semver: qué significan los tres números de versión, cómo interpretar los operadores de rango y por qué actualizar dependencias sin entender semver es una receta para desastres.

Al terminar, sabrás exactamente qué actualizaciones accepting y cómo leer changelogs para anticipar problemas.

  • Cada número tiene un significado específico.
  • Semver sigue el formato major.minor.patch. El primer número (major) cambia cuando hay breaking changes incompatibles con versiones anteriores. El segundo (minor) añade funcionalidad nueva pero compatible hacia atrás. El tercero (patch) corrige bugs sin cambiar la API.
  • Esta convención permite a los desarrolladores saber instantáneamente el impacto de actualizar un paquete. 'Actualicé React de 17 a 18 y todo rompió' → major cambió. 'Actualicé a la última versión y seguí trabajando' → minor o patch cambió.
  • Major (1.0.0 → 2.0.0): breaking changes, API incompatible
  • Minor (1.0.0 → 1.1.0): nueva funcionalidad, compatible

Anatomía de una versión: major.minor.patch

Cada número tiene un significado específico.

Semver sigue el formato major.minor.patch. El primer número (major) cambia cuando hay breaking changes incompatibles con versiones anteriores. El segundo (minor) añade funcionalidad nueva pero compatible hacia atrás. El tercero (patch) corrige bugs sin cambiar la API.

Esta convención permite a los desarrolladores saber instantáneamente el impacto de actualizar un paquete. 'Actualicé React de 17 a 18 y todo rompió' → major cambió. 'Actualicé a la última versión y seguí trabajando' → minor o patch cambió.

  • Major (1.0.0 → 2.0.0): breaking changes, API incompatible
  • Minor (1.0.0 → 1.1.0): nueva funcionalidad, compatible
  • Patch (1.0.0 → 1.0.1): bug fixes, compatible

Operadores de rango: ^, ~, >, <, y más

Cómo especificar qué versiones aceptas.

Cuando instalas un paquete sin especificar versión exacta, npm usa operadores de rango. El más común es ^ (caret): ^4.17.21 significa 'acepta cualquier minor y patch, pero no major'. Entonces 4.18.0 y 4.17.22 están permitidas, pero 5.0.0 no.

El operador ~ (tilde) es más restrictivo: ~1.0.0 permite solo patches (1.0.1, 1.0.5) pero no minor (1.1.0). Esto es más seguro pero puede perder actualizaciones de funcionalidad.

^ vs ~: cuál elegir y cuándo

La diferencia entre confianza y seguridad.

El caret (^) es el operador por defecto cuando instalas paquetes sin versión específica. Asumes que el autor sigue semver y solo hace breaking changes en major. Esto te da acceso a mejoras y fixes sin mucho trabajo.

El tilde (~) es más conservador. Úsalo cuando necesitas máxima estabilidad o cuando el paquete tiene historial de cambios problemáticos en minor. El downside es que pierdes mejoras de funcionalidad.

  • ^ (caret): mayor flexibilidad, acceso a features nuevas
  • ~ (tilde): mayor estabilidad, solo patches
  • Exact: solo esa versión, máxima precaución

Rangos avanzados: AND, OR, prereleases

Para casos específicos y versionesbeta.

Puedes combinar rangos con || (OR) o espacios (AND). Por ejemplo, >=1.0.0 <2.0.0 || ^3.0.0 acepta versiones de 1.x o 3.x. También existen prereleases: 1.0.0-alpha.1 es anterior a 1.0.0 y npm trata estos rangos de forma especial.

Los prereleases (alpha, beta, rc) permiten probar versiones antes del lanzamiento oficial. Son útiles para librerías que publican betas.

package-lock.json: la red de seguridad

Por qué el lockfile es tu mejor amigo.

El package-lock.json registra exactamente qué versión de cada dependencia (incluyendo dependencias transitivas) se instaló. Cuando otra persona hace npm install, obtiene exactamente las mismas versiones, sin importar los rangos en package.json.

Esto elimina el 'funciona en mi máquina' por diferencias de versiones. El lockfile debe comprometerse al repositorio y actualizarse solo intencionalmente con npm install.

NPM
06

Versionado semántico (semver): el sistema que evita breaking changes

Entiende cómo funciona semver y por qué ^, ~ y los rangos de versiones son cruciales. Aprende a evitar breaking changes accidentales y a actualizar dependencias de forma segura.

Código del tema: ^1.0.0

📘 Teoría

Anatomía de una versión: major.minor.patch

Cada número tiene un significado específico.

Semver sigue el formato major.minor.patch. El primer número (major) cambia cuando hay breaking changes incompatibles con versiones anteriores. El segundo (minor) añade funcionalidad nueva pero compatible hacia atrás. El tercero (patch) corrige bugs sin cambiar la API.

Esta convención permite a los desarrolladores saber instantáneamente el impacto de actualizar un paquete. 'Actualicé React de 17 a 18 y todo rompió' → major cambió. 'Actualicé a la última versión y seguí trabajando' → minor o patch cambió.

  • Major (1.0.0 → 2.0.0): breaking changes, API incompatible
  • Minor (1.0.0 → 1.1.0): nueva funcionalidad, compatible
  • Patch (1.0.0 → 1.0.1): bug fixes, compatible

Operadores de rango: ^, ~, >, <, y más

Cómo especificar qué versiones aceptas.

Cuando instalas un paquete sin especificar versión exacta, npm usa operadores de rango. El más común es ^ (caret): ^4.17.21 significa 'acepta cualquier minor y patch, pero no major'. Entonces 4.18.0 y 4.17.22 están permitidas, pero 5.0.0 no.

El operador ~ (tilde) es más restrictivo: ~1.0.0 permite solo patches (1.0.1, 1.0.5) pero no minor (1.1.0). Esto es más seguro pero puede perder actualizaciones de funcionalidad.

Ejemplos de operadores de rango
# ^4.17.21 = mayor o igual a 4.17.21, menor a 5.0.0
# ~1.0.0 = mayor o igual a 1.0.0, menor a 1.1.0
# >=1.0.0 = mayor o igual a 1.0.0
# 1.0.0 = exactamente 1.0.0
# >1.0.0 <2.0.0 = entre 1.0.0 y 2.0.0

^ vs ~: cuál elegir y cuándo

La diferencia entre confianza y seguridad.

El caret (^) es el operador por defecto cuando instalas paquetes sin versión específica. Asumes que el autor sigue semver y solo hace breaking changes en major. Esto te da acceso a mejoras y fixes sin mucho trabajo.

El tilde (~) es más conservador. Úsalo cuando necesitas máxima estabilidad o cuando el paquete tiene historial de cambios problemáticos en minor. El downside es que pierdes mejoras de funcionalidad.

  • ^ (caret): mayor flexibilidad, acceso a features nuevas
  • ~ (tilde): mayor estabilidad, solo patches
  • Exact: solo esa versión, máxima precaución

Rangos avanzados: AND, OR, prereleases

Para casos específicos y versionesbeta.

Puedes combinar rangos con || (OR) o espacios (AND). Por ejemplo, >=1.0.0 2.0.0 || ^3.0.0 acepta versiones de 1.x o 3.x. También existen prereleases: 1.0.0-alpha.1 es anterior a 1.0.0 y npm trata estos rangos de forma especial.

Los prereleases (alpha, beta, rc) permiten probar versiones antes del lanzamiento oficial. Son útiles para librerías que publican betas.

Rangos avanzados
# Combinaciones
">=1.0.0 <2.0.0 || >=3.0.0"

# Rango con AND
">=1.0.0 <2.0.0"

# Prereleases
"^1.0.0-alpha.1"

package-lock.json: la red de seguridad

Por qué el lockfile es tu mejor amigo.

El package-lock.json registra exactamente qué versión de cada dependencia (incluyendo dependencias transitivas) se instaló. Cuando otra persona hace npm install, obtiene exactamente las mismas versiones, sin importar los rangos en package.json.

Esto elimina el 'funciona en mi máquina' por diferencias de versiones. El lockfile debe comprometerse al repositorio y actualizarse solo intencionalmente con npm install.

Ver el lockfile
# Ver qué versión exacta está instalada
npm list lodash

# Ver árbol de dependencias
npm list

# Actualizar lockfile con la última versión
npm install

🧪 Aprende probando

Ejemplo Ejemplo: interpretar operadores Determina qué versiones acepta cada rango.

🏁 Retos

Reto Reto 1: Elegir el operador correcto Elige el operador según el nivel de estabilidad deseado.
Reto Reto 2: Verificar versiones con npm list Usa npm list para ver las versiones instaladas.

🧰 Recursos

Test

Comprueba tus conocimientos con un test sobre NPM.

Test de NPM

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros 😉.

Esta la hice en febrero de 2026 para facilitar el aprendizaje de mis alumnxs. Aprender desarrollo web practicando. La idea es que crezca semanalmente con nuevos temas, tests y retos.

Inspirado en MDN, en W3Schools, en Codepen, en el crack de Manz y en mil sitios de documentación sobre desarrollo web. Quería aportar además de bloques teóricos con ejemplos, la gamificación de los retos y el sistema de test que ya tenía en culTest .

Si te gustó, si no te gustó, si quieres saludarme, o invitarme a 🍻 no dudes en escribirme en cristianeslava@gmail.com .