Node.js: Cómo construir un paquete para npm

¡Buen día gente! Hoy decido comenzar una serie de tutoriales para orientar a los nuevos usuarios de Node.js acerca de qué cosas hacer y cómo hacerlas con esta maravillosa plataforma

El tutorial de hoy girará en torno a cómo se crean módulos para Node y cómo se publican en npmjs.org para que estén al alcance de toda la comunidad. Si por esas casualidades llegaste al blog y no sabes de qué estoy hablando, a continuación te presento a las estrellas.


Node.js

Tal cual lo dice su sitio oficial, Node.js es una plataforma construida sobre el motor JavaScript V8 y orientada al desarrollo de todo tipo de aplicaciones de red de forma rápida, fácil y escalable. Node.js es, básicamente, Javascript implementado en el servidor.


npm

npm es el gestor de paquetes de Node.js por excelencia. Esta una herramienta de línea de comandos que permite gestionar todas las dependencias de una aplicación hecha en Node.js. Si, por ejemplo, queremos usar el módulo de underscore en nuestro proyecto, solo tenemos que ejecutar el siguiente comando:

[email protected]:~
[email protected]:~$ npm install underscore
[email protected]:~$

Puedes encontrar más info de npm en su sitio oficial.

Bien, aclarados estos dos puntos, vamos a construir nuestro primer módulo.


Requisitos

  • Node.js y npm (muy obvio, pero vale aclararlo).
  • Café, mucho café


Objetivo

Vamos a crear una aplicación que reemplace parámetros del tipo %clave% con una cadena que nosotros le vamos a proveer. Por ejemplo:

-> Cadena de entrada: %home_dir%/Proyectos
-> Operación: %home_dir% => /home/sergio
-> Cadena de salida: /home/sergio/Proyectos

¡Manos a la obra!

Node.js: Estructura de directorios

Esto no es precisamente un estándar sino más bien una convención entre desarrolladores acerca de cómo ordenar nuestro código fuente escrito para NodeJS. Para este proyecto vamos a ordenarlo de la siguiente manera:

param_replacer/
 ├── bin/
 |   └─ param_replacer
 ├── lib/
 |   └─ param_replacer.js
 ├── index.js
 ├── README.md
 └── package.json


¿Qué hay en bin/ ?

Puedes colocar un script que permita la ejecución de tu aplicación desde la línea de comandos sin llamar a node. No es mágico, obviamente, pero sirve de mucho para cuando instalemos el paquete. Para nuestra aplicación de ejemplo no lo vamos a utilizar, así que será tema de otro artículo.

¿Qué hay en lib/ ?

Dentro de lib “aislaremos” todo el código de la aplicación. Es una manera de tener ordenado el directorio principal del paquete.

¿Qué hay en el directorio principal?

En el mismo creamos un index.js que sirve de atajo al script principal de nuestra aplicación, un README.md (o README.markdown) que será mostrado como readme por defecto en la página de nuestro paquete, en el sitio de npm, y por último tenemos nuestro apreciado package.json. Este último archivo es indispensable a la hora de publicar nuestros módulos en npm, ya que el mismo contiene toda la info relevante como nombre del paquete, versión, colaboradores, keywords, dependencias, etc.

En breve veremos más acerca de package.json y cómo configurar cada detalle del mismo.

Node.js: La función de reemplazo

Comenzaremos a programar Como les comenté, toda la lógica de la aplicación fue a parar a lib/param_replacer.js. Editemos ese archivo y juguemos.

> Enlace al código <

Como vemos en la salida, nuestro script está reemplazando cualquier cosa encerrada entre % por un valor único. Podríamos mejorar un poco su comportamiento haciendo lo siguiente:

> Enlace al código <

Mucho mejor. Con esta forma de aislar parámetros con sus reemplazos podemos jugar de muchas maneras, como por ejemplo, hacer un “hello world” multi idiomas:

> Enlace al código <

Y ejecutamos:

[email protected]:~/Proyecto/PaqueteNodejs
[email protected]:~/Proyecto/PaqueteNodejs$ node lib/param_replacer.js
[email protected]:~/Proyecto/PaqueteNodejs$

Bien, con esto ya tenemos la funcionalidad principal cubierta. Pero no es más que simple Javascript. ¿Dónde está la magia de Node.js y npm? Sigamos debajo…

Node.js: Código modular

Una de las cosas que hacen a Node.js una plataforma sólida es la manera en la que soluciona el aislar y exponer el código, similar al require de PHP, pero robusto como el import de Python.

Los módulos en Node.js se definen en un archivo .js, .json o .node y luego pueden ser importados en otros lugares de nuestra aplicación mediante el método require. Por ejemplo, si tenemos un módulo definido dentro de lib/param_replacer.js y queremos usarlo dentro de un archivo lib/otro_archivo.js, solo basta con escribir:

> Enlace al código <

Dentro de la variable replacer tendremos a nuestro querido reemplazador de parámetros. Pero, ¿cómo se define un módulo?

Creando un módulo

Cuando invocamos al require, Node.js lee el archivo que solicitamos y asigna el contenido del módulo a nuestra variable. Nuestro archivo no expone absolutamente todo el código, sino aquel que sea “exportado”. Para ello se utiliza el método exports.

Modifiquemos nuestro param_replacer.js para que pueda exponer su funcionalidad:

> Enlace al código <

Con esta modificación, nuestro código quedó completamente aislado en un archivo separado del resto, y expone un único método llamado replace que no es ni más ni menos que una función anónima.

Para ver a nuestro renovado replacer en acción, copiar el siguiente código en index.js:

> Enlace al código <

Y ejecutamos:

[email protected]:~/Proyecto/PaqueteNodejs
[email protected]:~/Proyecto/PaqueteNodejs$ node index.js
[email protected]:~/Proyecto/PaqueteNodejs$

Genial, nuestra aplicación se comporta de la misma manera, pero ahora es modular ¿Qué mas hay que hacer?

Node.js: Carga de módulos

Ya vimos que desde el index.js de nuestro módulo se pueden hacer algunas pruebas rápidas, pero en estos casos el index cumple una función muy importante. Según la documentación de Node.js, cuando hacemos un require el compilador comienza a buscar por el archivo que estemos solicitando (algo obvio). Puede buscar un archivo específico (si defines su extensión) o bien por un archivo con extensiones .js, .json o .node, en ese orden de fallbacks. Veamos un ejemplo de todo esto.

Imaginemos que tenemos un módulo llamado mi_libreria.js y queremos usarlo en otro archivo:

> Enlace al código <

En este caso, Node.js buscará sólamente el archivo especificado. Pero también podemos usar el require de esta otra forma:

> Enlace al código <

Al no especificar una extensión, Node.js buscará primero un archivo llamado mi_libreria.js. En caso de no encontrarlo, intentará con mi_libreria.json y si así mismo falla, tratará con mi_libreria.node.

¿Y dónde intervienen los index.js?

En caso de tener problemas con la carga especificada anteriormente, el cargador de archivos intentará una última cosa… Buscar un archivo index dentro del directorio mi_libreria. Con los index sucede lo mismo que con otros archivos, buscará:

- ./mi_libreria/index.js
- ./mi_libreria/index.json
- ./mi_libreria/index.node

Si todo falla, el compilador explota de manera horrenda.

Entonces, ¿qué hacemos con el index.js actual? Apenas comencé el artículo, les comenté que se iba a usar de atajo para incluir nuestra librería principal. Así que reemplacemos todo el contenido por esto:

> Enlace al código <

Con esta modificación podemos utilizar la librería como un paquete completo, sólo copiando el directorio donde estamos trabajando (param_replacer/) y haciendo require('param_replacer'); cuando lo necesitemos…

mi_app/
 ├── liberias/
 |   └─ libs.js
 ├── node_modules/
 |   └─ param_replacer/
 ├── app.js ← este archivo puede hacer require('param_replacer') y todo funciona de maravillas
 └── otro.js

Y esto no es todo, como les mostré arriba, existe un directorio mágico llamado nodemodules que es el que contiene módulos de nuestras aplicaciones. El cargador de _Node.js también buscará por módulos dentro de ese directorio, siguiendo los criterios de carga que ya vimos. Genial, ¿no? Si quieren aprender más sobre esto, consulten la documentación oficial.

Y este es el momento justo de presentar a nuestro héroe, npm.

npm: Configurando el paquete

Al momento en que publiquemos en npm, todo el contenido que tenemos dentro del directorio param_replacer será el contenido del paquete que estará en los repositorios de npm. Además, un archivo package.json sirve para configurar este paquete. Veamos un ejemplo:

> Enlace al código <

En este o este otro enlace encontrarán una descripción completa sobre todas las configuraciones que podemos cubrir con package.json.

npm: Publicando nuestro primer paquete

En este punto voy a considerar que nunca has creado una cuenta en NPM, así que voy a arrancar desde cero. Antes que nada necesitamos registrar un usuario para poder publicar. Se puede hacer de dos maneras, la trivial y la geek

Forma trivial

Simplemente ingresando en la página de registro, podemos completar nuestros datos y darnos de alta. ¡Recuerden su nombre de usuario y contraseña!.

A continuación, vas a la consola y ejecutas:

[email protected]:~/Proyecto/PaqueteNodejs
[email protected]:~/Proyecto/PaqueteNodejs$ npm adduser
[email protected]:~/Proyecto/PaqueteNodejs$

Provees tus credenciales y listo.

Forma geek

Decidí llamarlo así ya que no se usan los métodos web, sino que se usa la aplicación de consola. Ejecutar lo siguiente:

[email protected]:~/Proyecto/PaqueteNodejs
[email protected]:~/Proyecto/PaqueteNodejs$ npm adduser
[email protected]:~/Proyecto/PaqueteNodejs$

Es el mismo comando que usamos en la forma trivial. El mismo registra un nuevo usuario y configura, o configura solamente tu cuenta, dependiendo de si tenias un usuario registrado previamente (caso de que hayas registrado en web, o cambies de PC).

Para finalizar, sigues los pasos y ¡voila! Ya podemos publicar nuestro trabajo.

Publicando el paquete

Asegúrate de estar en el directorio principal (donde está el package.json). Una vez ahí, ejecuta:

[email protected]:~/Proyecto/PaqueteNodejs
[email protected]:~/Proyecto/PaqueteNodejs$ npm publish
[email protected]:~/Proyecto/PaqueteNodejs$

Ahora intenta instalarlo en alguno de tus proyectos:

[email protected]:~/Proyecto/OtroProyecto
[email protected]:~/Proyecto/OtroProyecto$ npm install param_replacer
[email protected]:~/Proyecto/OtroProyecto$

O instálalo para que esté disponible de modo global (en todos tus proyectos):

[email protected]:~
[email protected]:~$ npm install -g param_replacer
[email protected]:~$



npm: Administrando nuestros paquetes

Como es obvio, en todo proyecto siempre hay corrección de errores o se añaden funcionalidades nuevas. Para actualizar el paquete publicado, solo tienes que cambiar el valor de version y ejecutar nuevamente npm publish.

Si cometiste un error, ¡no importa! npm uninstall y npm unpublish lo solucionarán.



Bueno gente, eso fue todo por el momento. Si lo desean, pueden echarle un ojo a este proyecto en Github y si tienen alguna duda, ¡no duden en hacérmela saber!

¡Hasta la próxima!

Comentarios

comments powered by Disqus

Los comentarios están deshabilitados debido a que has rechazado las cookies en este sitio.

Restablecer Cookies
Copyright © 2014 - Sergio Lepore
Desarrollado con Hexo y alojado en Github

Nota legal: Las opiniones expresadas en el presente blog son mis opiniones personales y bajo ningún modo representan la opinión de mi empleador
Política de Cookies