node

¿Pero qué demonios es package-lock.json?

nodejs

package-lock.json es un fichero muy importante que te evitará un montón de problemas en tus repositorios.

Pero antes de entrar en la discusión acerca de package-lock.json vamos a hablar un poco acerca de el versionado semántico y package.json.

Versionado semántico

El versionado semántico o SemVer (Semantic Versioning) es la forma ideal de versionar paquetes.  Normalmente se versionan como 2.3.5 (major.minor.patch)

semver

  • Bug fix/patch version
    Incluye correcciones de bugs, errores de documentación, gramaticales, etc.
  • Minor version
    Incluye nuevas API’s o funcionalidades que no rompen nada de las versiones anteriores, de modo que lo que funciona en v1.1.0 debería funcionar también en v1.9.0.
  • Major version
    Incluye código que rompe las cosas.  Puede ser la eliminación de API’s o el cambio de nombre de funciones de modo que lo que funciona en v1.0.0 no funcionará necesariamente en v2.0.0

package.json

package.json es un fichero que contiene información acerca de tu proyecto (nombre, versión, etc) además de listar los paquetes de los que depende.

{
  "name": "ng7-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~7.0.0",
    "@angular/common": "~7.0.0",
    "@angular/compiler": "~7.0.0",
    "@angular/core": "~7.0.0",
    "@angular/forms": "~7.0.0",
    "@angular/http": "~7.0.0",
    "@angular/platform-browser": "~7.0.0",
    "@angular/platform-browser-dynamic": "~7.0.0",
    "@angular/router": "~7.0.0",
    "core-js": "^2.5.4",
    "rxjs": "~6.3.3",
    "zone.js": "~0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.10.0",
    "@angular/cli": "~7.0.1",
    "@angular/compiler-cli": "~7.0.0",
    "@angular/language-service": "~7.0.0",
    "@types/node": "~8.9.4",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "~4.5.0",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~3.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.11.0",
    "typescript": "~3.1.1"
  }
}

Como puedes ver en el código anterior, tras cada dependencia listada en package.json hay un número como ^2.5.4 o ~7.0.0 que indica la versión del paquete, pero antes de la versión hay un ^ o un ~.  Ese pequeño ^ o ~ puede ser el causante de un desastre total en nuestro proyecto.

El signo ^ de antes de la versión indica a npm que si alguien clona el proyecto y ejecuta npm install en el directorio, lo que debe hacer es instalar en su node_modules la última minor version del paquete.  En el caso de ~ se trataría de la última fix version.

Nota: Para más información puedes consultar la documentación oficial.

Digamos, por ejemplo, que tenemos en package.json una dependencia de express ^2.20.0 y que más tarde el equipo de express saca la versión 2.24.0.  Si ahora alguien clona nuestro repositorio y ejecuta npm install, obtendrán la versión 2.24.0.

Sin embargo  esto puede ser un problema si los desarrolladores del paquete «rompen» alguna funcionalidad en la minor version lo que puede hacer que nuestra aplicación falle.

Para evitar este escenario los desarrolladores de npm crearon un nuevo fichero llamado package-lock.json.

package-lock.json

package-lock.json sencillamente evita este comportamiento general de actualizar versiones minor o fix de modo que cuando alguien clona nuestro repositorio y ejecuta npm install en su equipo, npm examinará package-lock.json e instalará la versión exacta de los paquete que nosotros habíamos instalado, ignorando así los ^ y ~ de package.json.

Realmente npm install no ignora las versiones de package.json así como no ignora package-lock.json.  Lo que hace es verificar que package.json y package-lock.json están en sincronía.  Esto es, si las SemVer‘s descritas en package.json concuerdan con las versiones fijadas en package-lock.json, npm install usará estas última completamente (igual que haría npm ci).

Sin embargo si modificas package.json de modo que las versiones en package-lock.json ya no son válidas, npm install actuará como si hubieses ejecutado un npm install some-pkg@x.y.z, donde x.y.z es la nueva versión de some-pkg que aparece en package.json.

Nota: Para más información puedes consultar la documentación oficial.

Supongamos que hemos creado el proyecto ‘project‘ y hemos ejecutado npm install –save vue-extra@1.0.0.  Ahora lo clonamos tres veces: ‘project-clone-1‘, project-clone-2‘ y ‘project-clone-3‘.

  • project-clone-1
    En project-clone-1 tenemos el mismo package.json y package-lock.json que en el project original (lo que significa que no hemos cambiado nada manualmente) y al ejecutar npm install se instala la misma versión v1.0.0 de vue-extra que se instaló en el project original.
  • project-clone-2
    En project-clone-2 también teníamos el mismo package.json y package-lock.json pero en esta ocasión, en vez de ejecutar un npm install, ejecutamos un npm install –save vue-extra lo que hace que se actualice el paquete, cambiando los ficheros package.json y package-lock.json e instaladon la última versión de vue-extra que es la v1.1.4.
  • project-clone-3
    En project-clone-3 hemos abierto package.json y hemos cambiado manualmente vue-extra^1.0.0» por «^1.1.4«.  Luego hemos ejecutado npm install.  Aquí, al haber actualizado manualmente package.json, npm considera a package.json la verdad absoluta, de modo que instala la versión v1.1.4 de vue-extra y además actualiza package-lock.json con dicha versión.

vía

Una respuesta a “¿Pero qué demonios es package-lock.json?

  1. Hola, Rubén, acabo de encontrarme con tu blog de casualidad buscando información sobre este tema y me ha parecido muy útil y la entrada y muy interesante el blog. Gracias por compartirlo!

Deja un comentario