El fichero package-lock.json ¿Tengo que versionarlo?

34293010980_cbb8882bc6_o.jpg

Fotografía de portada de Chris Garcia

Si habéis actualizado estas semanas NPM a la versión 5, cuando hayáis usado alguno de los comandos, habréis apreciado un nuevo fichero al lado de vuestro package.json: el nuevo fichero package-lock.json.

Los que estáis acostumbrados a trabajar con YARN, no os habrá parecido nada extraña esta nueva funcionalidad de NPM, pero los que, como yo, nunca llegamos a cambiar de gestor de paquetes, este ficheros nos ha traído, por lo menos, curiosidad.

En el post de hoy explicaremos de qué trata este fichero, averiguaremos si es algo importante y comentaremos si hay necesidad de versionarlo en nuestro repositorio de Git o SVN, o si por el contrario lo tenemos que enviar al baúl de ignorados.

Nuestro problema

No se si a vosotros os ha pasado, pero hace unos años, descargar todas las dependencias que tenía un proyecto de NodeJS era un auténtico tormento. Sin saber por qué, lo que a tu compañero o compañera le estaba funcionando correctamente, a ti no te funcionaba o te daba problemas.

Teníamos las mismas dependencias, el package.json se encontraba actualizado, todos hacíamos un npm update ¿Cuál era el problema? El problema podía venir por varios motivos, pero uno de los más normales solía ser la forma en la que indicábamos la versión de las dependencias en el package.json.

Por ejemplo, imaginemos que tenemos el siguiente package.json con estas dependencias:

{
    ...
    dependencies: {
        package1: ^1.4.5,
        package2: ~3.5.6
    }
    ...
}

Esta forma de indicar mis dependencias indica que, del paquete package1, puede instalarse en mi proyecto aquellas versiones que cumplan 1.x.x y del package2 todas aquellas versiones nuevas que cumplan con 3.5.x.

Si recordamos la especificación de semver, el segundo número indica un cambio en la API, pero sin rotura de la anterior o con indicadores de que está obsoleto. El tercer número indica corrección de bugs.

Por tanto, puede llegar a tener sentido que nuestro proyecto quiera tener versiones nuevas de los paquetes con los bugs corregidos y con nueva funcionalidad que no rompa la que yo ya tenía.

El problema viene en que NodeJS es una plataforma tan diversa como inestable y si bien, el sistema semver tendría que ser así, no todos los equipos respetan esta nomenclatura a rajatabla, pudiendo pasar que alguien del equipo se haya instalado hace un mes una versión, y que alguien nuevo se baje las dependencias con una librería nueva que rompa todo.

Así que muchas veces, si queremos estabilidad, nos curamos en salud e intentamos poner las dependencias lo más fijas posibles:

{
    ...
    dependencies: {
        package1: 1.4.5,
        package2: 3.5.6
    }
    ...
}

De esta manera sé, que lo que se descarga a mi equipo siempre son las versiones 1.4.5 del paquete 1 y 4.5.6 del paquete 2.

Ahora bien, esto soluciona el problema en su justa medida. Un proyecto NodeJS se contempla como un árbol de dependencias. Mi proyecto tiene unas dependencias que a su vez tienen otras dependencias. Nosotros no tenemos control sobre los package.json de nuestras dependencias, por tanto, podemos estar sufriendo el mismo problemas en zonas más profundas del árbol.

Sin comerlo ni beberlo tenemos un proyecto indeterminista.

¿Qué me aporta el determinismo?

El determinismo es aquello que en el cual se produce siempre el mismo efecto debido a la misma causa. Es decir, que si por ejemplo, pongámonos en un caso programático, yo tengo una función que recibe unos parámetros (causa), la función siempre devolverá los mismos valores (efecto).

En NodeJS, hasta ahora, el determinismo no se estaba cumpliendo siempre. Yo podía bajarme 20 dependencias con unas versiones específicas un día en mi node_modules que 2 meses después no tenían porqué ser exactamente esas 20 dependencias con sus mismas versiones específicas.

El fichero package.json se queda limitado porque solo nos permite ser deterministas con el siguiente nivel del árbol, pero ¿qué ocurre con los siguientes niveles? Es aquí donde entra en juego el nuevo fichero package-lock.json.

Este fichero se encarga de presentar un snapshot del árbol de dependencias que estamos incluyendo en un proyecto. Es una forma de convertir nuestro proyecto en determinista. Si tenemos un fichero donde se indique qué se esta instalando en node_modules y con qué versión, cualquier persona del equipo, cuando ejecute npm install, será capaz de reproducir el mismo árbol que el de su compañero sin problemas asociados.

Ganamos en estabilidad dentro de los proyectos.

¿Cómo es este fichero por dentro?

El fichero es un JSON convencional con metainformación del proyecto. Un ejemplo puede ser este:

{
    "name": "mi_proyecto2",
    "version": "1.0.0",
    "lockfileVersion": 1,
    "dependencies": {
        "content-type": {
            "version": "1.0.2",
            "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
            "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0="
        },
        "cookie": {
            "version": "0.3.1",
            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
            "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
        }
        ...
    }
}

name y version indican la versión en la que se encuentra el package.json es la forma de encontrarse sincronizados. lockfileVersion es la versión del esquema del fichero package-lock.json. Han querido cubrirse las espaldas por si el día de mañana deciden añadir cambios en este fichero. De esta manera, sabemos en que versión empezó a generarse.

dependencies contiene todas las dependencias de nuestro árbol ya sean directas o indirectas. Cada dependencia tiene la versión exacta que se instaló y el registry desde el que se hizo. Además añade una pequeña huella de integridad para dar seguridad al sistema. De esta manera nadie podrá cambiar el fichero a mano ya que este hash es autocalculado.

Pon esto, NPM es capaz de reproducir imágenes exactas de node_modules de un ordenador a otro.

Entonces ¿Debo versionarlo?

Parece obvio que sí. No es obligatorio para que tu proyecto funcione, pero tiene sentido que si queremos hacer que nuestros proyectos sean mas estables que tengamos que subirlo.

Puede llegar a parecer un fichero de log, sin embargo contiene información valiosa para un equipo. Por ejemplo, al poder versionar el fichero, estamos dejando una traza de cómo y cuándo se instalaron los paquetes en nuestro proyecto. Creo que puede ser una información valiosa en proyectos grandes y auditorias internas.

Por tanto, te digo que lo subas encarecidamente.

Lo importante del fichero está contado, por ahora lo dejamos aquí.

Nos leemos 🙂

 

 

Anuncios

One comment

  1. alejandro · julio 8

    Excelente explicación, no tenia idea de que era ese archivo, jaja. Gracias!

    Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s