Si hay un proyecto que ha marcado como ningún otro el panorama de NodeJS, ese es sin duda NPM. Se trata del gestor de paquetes que usamos a diario todos los desarrolladores de Node y que fue iniciado hace ya varios años por Isaac Z. Schlueter. Creo que no me equivoco al decir que la actual comunidad de NodeJS no sería lo que es sin este proyecto. Es más, creo que ha tenido tanto éxito en la forma de gestionar las dependencias de un proyecto, de una forma tan explícita y aparentemente simple, que han salido soluciones similares en otros lenguajes.

En el momento de escribir este artículo, NPM contaba con:

  • 134.847 paquetes en total.
  • 46.049.121 de paquetes descargados al día.
  • 37 millones de visitas a la web.
  • Picos de 2100 req/seg.

Con estas cifras queda claro el papel predominante que tiene NPM dentro de la comundad de NodeJS.

Llegados a este punto, es posible que sientas que tú también quieres colaborar con la comunidad y que tienes una idea sobre un paquete que podría ayudar a otros desarrolladores en su día a día. ¡Eso es genial! y deberías colaborar. En este post te mostraré cómo crear un paquete NPM nivel pro.

A la hora de publicar tu paquete hay un serie de reglas que debes seguir:

  • Haz que tu código sea accesible para cualquier miembro de la comunidad, en caso de que alguien quiera leerlo o incluso modificarlo. Yo uso Github, y también tengo algunas cosas en Bitbucket.

  • Facilita que otros desarrolladores encuentren tu paquete mediante etiquetas claras y precisas cuando crees tu fichero package.json.

  • Incluye tests. No hay nada más sospechoso que ir al repositorio de un paquete que que no tenga una carpeta tests. Además, si los tienes, siempre puedes colocarlos en el prepublish script y ahorrarte subir una versión que no funciona correctamente.

  • Sube solo lo imprescindible a la repo. Sobre todo no subas nada que se pueda generar automáticamente en el proceso de instalación.

  • Sube solo lo imprescindible al registro de NPM. Es decir, sube solo lo necesario para que tu paquete funcione. No hay que subir ni la documentación, ni los tests, ni los ficheros que deban pasar por un transpiler como CoffeeScript o Babel. Piensa que nadie va a mirar nunca lo que se baja NPM al instalar un paquete y, si lo hace, es que algo ha salido muy mal.

  • Lo más importante, el README. Documenta tu paquete de la manera más exhaustiva posible. Asegúrate de que tenga una sección de instalación, otra que comente posibles dependencias externas que no puedes controlar con NPM, y tantos ejemplos de uso y casos de uso como creas necesario. Tampoco estaría de más si al pie del README pones la licencia de uso, aunque seguramente también la pondrás en el package.json.

Dicho todo esto, vamos a ver un ejemplo real de cómo llevar a cabo la publicación de un paquete.

(1) Creamos el repo que vamos a utilizar para nuestro proyecto. En mi caso, creo un repositorio llamamado sequence-title. Luego creamos nuestro directorio de trabajo.

$ mkdir sequence-title
$ cd sequence-title
$ git init
$ git remote add origin https://github.com/carlosvillu/sequence-title
$ npm init

Si llamas a npm init después de crear el repositorio de git, NPM automáticamente asociará el repositorio a tu paquete.

(2) Creamos los ficheros que usará NPM para evitar subir ficheros no esenciales al registro:

$ touch .npmignore

Dentro de ese fichero colocamos:

node_modules  
src  
test  
Gruntfile.coffee  
npm-debug.log  

Con ello evitamos subir node_modules, nuestra carpeta de fuentes no compiladas, nuestra carpeta de tests, el fichero grunt --que no necesitamos para nada en producción-- y algún fichero de log. La idea de este fichero es filtrar todo lo que no sea absolutamente imprescindible para ejecutar el módulo.

(3) Evitamos subir a Github cualquier cosa que no se pueda generar automáticamente:

$ touch .gitignore

y dentro colocamos:

node_modules  
lib/**/*.js  
npm-debug.log  

Sabemos que nunca debemos versionar la carpeta node_modules, pero también debemos evitar subir los ficheros producto de una compilación.

Cuando creas un proyecto en Github y le dices que es de Node, este ya te sugiere un fichero .gitignore. Asegúrate de agregarle tus ficheros compilados.

(4) Antes de publicar nuestro paquete en el registro, debemos asegurarnos de que tenemos la última versión de nuestro código compilado y que pasa todos los tests. Para ello usamos los hooks de NPM.

{
  "name": "sequence-titles",
  "version": "1.4.0",
  "description": "Sequence string in natural language",
  "main": "lib/",
  "scripts": {
    "prepublish": "grunt coffee",
    "test": "./node_modules/mocha/bin/mocha --compilers coffee:coffee-script/register test/**/*.coffee"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/carlosvillu/sequence-title"
  },
  "keywords": [
    "sequence",
    "PNL"
  ],
  "author": "Carlos Villuendas <carlosvillu@gmail.com>",
  "license": "MIT",
  "devDependencies": {
    "chai": "^1.10.0",
    "coffee-script": "^1.8.0",
    "grunt": "^0.4.5",
    "grunt-contrib-clean": "^0.6.0",
    "grunt-contrib-coffee": "^0.12.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-mocha-test": "^0.12.4",
    "mocha": "^2.0.1"
  }
}

Como vemos en el fichero package.jsonde nuestro repositorio de ejemplo, hay un hook prepublish que se encarga de compilar las fuentes y dejarlas en la carpeta libs. Este es también un lugar ideal para lanzar nuestro comando de tests.

Puedes crear tus propios hooks de NPM con solo anteponer pre* y post* al nombre de la tarea. Por ejemplo:

"scripts": {
    "preecho": "echo 'PreEcho'",
    "echo": "echo 'Echo'",
    "postecho": "echo 'PostEcho'"
  }

La salida de ejecutar este script con NPM sería:

(5) Sé cuidadoso con la versión de tu paquete. Cada vez que publiques una versión en el registro de NPM, debes crear también un tag en tu repositorio con esa versión. Te recomiendo seguir un versionado semántico. No te olvides, además, de corregir la versión en el fichero package.json.

Git release es un comando útil para taggear código en repositorios remotos. En este post explico la instalación de Git-extras.

Si te ha gustado este post, difunde la palabra. Tampoco dudes en dejar comentarios u observaciones. ¡Gracias! :)

Suscríbete a mi lista de correo

* Campos obligatorios