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.