Aprenda Node.js: una guía para principiantes

JavaScript es, sin duda, uno de los lenguajes de programación más populares que existen hoy en día, y por una buena razón. Se puede ejecutar fácilmente en su navegador, en un servidor,...

JavaScript es, sin duda, uno de los lenguajes de programación más populares que existen hoy en día, y por una buena razón. Puede ejecutarse fácilmente en su navegador, en un servidor, en su escritorio o incluso en su teléfono como una aplicación. Una de las formas más populares y sencillas de escribir JavaScript es usar Nodo.js.

Existen bastantes recursos para aprender Node.js, pero no muchos de ellos realmente le brindan los antecedentes, las herramientas y los recursos que necesita para tener éxito en la escritura de código de Node.

Entonces, lo que pretendo hacer aquí es brindarles una guía que desearía tener cuando recién comencé. Comenzaré con una breve descripción de lo que realmente es Node y lo que está haciendo detrás de la cortina, luego le daré algunos ejemplos concretos que puede probar usted mismo en el navegador, y finalmente yo Le daré un montón de recursos para guiarlo a través de algunos ejemplos/conceptos más útiles y prácticos.

Tenga en cuenta que esta guía no le enseñará cómo codificar, sino que lo guiará a través de los conceptos básicos del tiempo de ejecución de Node y npm.

¿Qué es el nodo

Node es un entorno de tiempo de ejecución multiplataforma del lado del servidor que se ejecuta en Motor JavaScript V8, que impulsa el navegador Chrome de Google. Este es realmente el corazón de Node y es el componente que realmente analiza y ejecuta el código.

El motor V8 hace esto al compilar JavaScript en código de máquina nativo, lo que lo hace mucho más rápido que un intérprete. Para acelerar aún más las cosas, el código compilado se optimiza (y se vuelve a optimizar) dinámicamente en tiempo de ejecución en función de la heurística del perfil de ejecución del código. Esto significa que a medida que se ejecuta el programa, el motor en realidad realiza un seguimiento de su rendimiento y hace que el código sea más rápido en función de ciertos factores que se rastrean.

Como tiempo de ejecución, el gran enfoque de Node es utilizar un modelo de E/S sin bloqueo y controlado por eventos para que sea ligero y rápido. Para algunos, este modelo de programación puede ser un poco confuso al principio, pero en realidad hace un gran trabajo al simplificar el desarrollo de aplicaciones de E/S pesadas, como sitios web.

Este diseño es ideal para optimizar el rendimiento y la escalabilidad de su código, que es una de las principales razones por las que se ha vuelto tan popular. Por ejemplo, alguien consiguió que manejara 600.000 conexiones websocket simultáneas , que es una locura. Ahora, tuvo que hacer un poco de configuración personalizada, pero eso no lo hace menos impresionante. Esta es exactamente la razón por la que empresas como IBM, Microsoft y PayPal utilizan Node para sus servicios web.

Ahora, Node ni siquiera necesita ser rápido para que sea atractivo. Una de mis funciones favoritas es el administrador de paquetes, npm. Muchos idiomas carecen de un buen administrador de paquetes como este. npm es una herramienta de línea de comandos que puede usar para inicializar módulos, administrar dependencias o ejecutar pruebas, entre otras cosas.

logotipo de npm

El repositorio público está abierto para que cualquiera pueda descargar y publicar código. En el momento de escribir este artículo, npm aloja más de 210 000 módulos, que van desde sitios web hasta herramientas de línea de comandos y contenedores de API.

Aquí hay un ejemplo de un paquete que creé. Puede ver que la página principal es el LÉAME, que describe qué hace el paquete y cómo usarlo. También obtiene un resumen rápido de otra información, como la cantidad de descargas, la ubicación del repositorio y la licencia de software utilizada.

Para qué es bueno Node

Entre otras cosas, Node es probablemente el más adecuado para crear sitios web y herramientas que requieren una interacción sincrónica en tiempo real. Los sitios/aplicaciones de chat son un buen ejemplo de esto, ya que suelen tener una gran cantidad de IO. El modelo basado en eventos sin bloqueo le permite manejar muchas solicitudes simultáneamente.

También es muy bueno para crear el front-end para las API web (a través de REST). Esto se debe a que está optimizado para E/S basada en eventos (que ya mencioné) y maneja JSON de forma nativa, por lo que se necesita muy poco o ningún análisis.

Qué nodo no es bueno para {#para quénoesbueno}

Por otro lado, veamos en qué no es bueno Node. En particular, es muy poco adecuado para realizar tareas informáticas pesadas. Así que si querías hacer algo como aprendizaje automático con Node, probablemente no tendrás la mejor experiencia.

Node también es todavía bastante joven, por lo que todavía está en rápido desarrollo. En los últimos meses hemos pasado de v0.12.x a v5.1.x. Entonces, si necesita algo más estable, probablemente esto no sea para usted.

Y en cuanto al "problema" de programación asíncrona, creo que la primera parte de esta respuesta de Quora lo explica bien:

[Su] falta de organización de código inherente es una gran desventaja. Se agrava especialmente cuando el equipo de desarrollo en su conjunto no está familiarizado con la programación asíncrona o los patrones de diseño estándar. Hay demasiadas formas de que el código se vuelva rebelde e imposible de mantener.

Aunque la programación asíncrona es algo bueno en general, agrega complejidad a sus programas.

El nodo REPL

Ok, a un poco de código. Comenzaremos de manera bastante simple y solo ejecutaremos algunos comandos en REPL (bucle de lectura-evaluación-impresión), que es solo una aplicación que le permite ejecutar de forma interactiva el código de Node en un shell. Un programa escrito aquí se ejecuta por partes en lugar de todo a la vez.

Asumiré que ya está familiarizado con JavaScript, por lo que solo revisaremos algunas cosas específicas de Node a lo largo de este artículo.

Probemos uno de los módulos integrados que vienen con Node, como el módulo crypto.

Suponiendo que ya tiene Node instalado, ejecute el comando node en su shell y escriba el siguiente código en el indicador línea por línea:

1
2
3
var crypto = require('crypto');

crypto.createHash('md5').update('hello world').digest('hex');

Después de ingresar la última línea en REPL (o al hacer clic en el botón 'ejecutar' arriba), debería ver 5eb63bbbe01eeed093cb22bb8f5acdc3 impreso en la consola.

El módulo crypto se carga usando la función require(), que maneja la resolución y la carga del código por usted. Más información sobre cómo funciona aquí.

Una vez que se ha cargado el módulo, puede usar sus funciones, que en este caso usamos createHash(). Dado que los REPL ejecutan el código por partes, normalmente imprimen el valor devuelto para cada línea, como vio aquí.

Puede usar REPL como este para probar rápidamente el código sin tener que escribirlo en un nuevo archivo y ejecutarlo. Es casi como un entorno sandbox de propósito general.

Tu primer programa

Los REPL son divertidos y todo eso, pero solo nos llevarán hasta cierto punto. Así que avancemos y escribamos nuestro primer programa de Nodo real. Todavía no nos preocuparemos por usar módulos de terceros (pero no se preocupe, lo haremos más adelante), así que primero veamos qué código incorporado está disponible para nosotros. Ya se le proporcionó una buena cantidad de código, que incluye (pero no se limita a):

  • fs: Envolturas simples proporcionadas sobre funciones POSIX estándar
  • http: un servidor y cliente HTTP de nivel inferior
  • os: proporciona algunos métodos básicos para informarle sobre el sistema operativo subyacente
  • ruta: Utilidades para manejar y transformar rutas de archivos
  • url: Utilidades para la resolución y análisis de URL
  • util: funciones de utilidad estándar como depuración, formateo e inspección

La cantidad de código incorporado no está al nivel de Python, pero hará el trabajo. Los beneficios reales vienen cuando comienza a ingresar a los módulos de terceros.

Para nuestro primer programa, crearemos una utilidad simple que determine su ubicación usando su dirección IP (un poco espeluznante, lo sé):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var http = require('http');

var options = {
    hostname: 'ipinfo.io',
    port: 80,
    path: '/json',
    method: 'GET'
};

var req = http.request(options, function(res) {
    var body = '';
    
    res.setEncoding('utf8');
    res.on('data', function(chunk) {
        body += chunk;
    });
    
    res.on('end', function() {
        var json = JSON.parse(body);
        console.log('Your location: ' + json.city + ', ' + json.region);
    });
});

req.end();

Copie el código anterior y péguelo en un archivo llamado 'index.js'. Luego, en la línea de comando, navegue hasta el directorio con el archivo que acaba de crear y ejecútelo con:

1
$ node index.js

Debería ver 'Su ubicación: [CIUDAD], [REGIÓN]' impreso en la línea de comando. La ciudad/región impresa probablemente estará bastante cerca de usted, pero no será exacta. Además, si no se imprime ninguna ciudad/región, eso solo significa que su información de IP no estaba en la base de datos.

Dado que este código no usa dependencias de terceros, no es necesario que tenga un archivo package.json o una carpeta node_modules, sobre lo cual explicaremos más en la siguiente sección.

Tu primer paquete

Tenga en cuenta que a lo largo de este artículo uso 'paquete' y 'módulo' indistintamente.

Para casi todos los sitios web/herramientas/proyectos que cree con Node.js, también querrá crear un módulo a su alrededor. Esto es para que pueda especificar dependencias, pruebas, scripts, repositorios, etc.

Un módulo típico consta de algunas cosas importantes:

  • paquete.json: un archivo JSON que contiene toda la información del módulo
  • node_modules/: Un directorio que contiene todas las dependencias
  • index.js: el archivo de código principal
  • README.md: Documentación sobre el módulo
  • test/: Un directorio de pruebas para el módulo

Hay muchas otras cosas que puede agregar a un módulo (como un archivo .npmignore, un directorio de documentos o archivos de configuración del editor), pero las cosas enumeradas anteriormente son algunas de las más comunes que verá.

Para mostrar cómo funciona todo esto, en el resto de esta sección crearemos nuestro propio paquete que se basa en el ejemplo anterior.

En lugar de simplemente decirle su ubicación en función de su dirección IP, utilizaremos algunos paquetes populares de Node para crear una herramienta que le permita encontrar la ubicación del servidor de cualquier sitio web. Lo llamaremos veinte (ver por qué).

Inicializando el paquete

Primero, cree y navegue a un nuevo directorio para su proyecto:

1
2
$ mkdir twenty
$ cd twenty

Luego, use npm para inicializar el proyecto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (twenty) 
version: (0.0.1) 
description: Locates the city/region of a given URL/IP address
entry point: (index.js) 
test command: 
git repository: 
keywords: 
license: (MIT) 
About to write to /Users/scott/projects/twenty/package.json:

{
  "name": "twenty",
  "version": "0.0.1",
  "description": "Locates the city/region of a given URL/IP address",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Scott Robinson <[correo electrónico protegido]> (https://wikihtp.com)",
  "license": "MIT"
}


Is this ok? (yes) yes

Complete cada solicitud (comenzando en nombre: (veinte)), o no ingrese nada y simplemente presione regresar para usar la configuración predeterminada. Esto creará un archivo package.json correctamente configurado que contiene el siguiente JSON:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "name": "twenty",
  "version": "0.0.1",
  "description": "Locates the city/region of a given URL/IP address",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Scott Robinson <[correo electrónico protegido]> (https://wikihtp.com)",
  "license": "MIT"
}

Este archivo es su punto de partida donde se guarda toda la información específica del proyecto.

Instalar dependencias

Para agregar dependencias a su proyecto, puede usar el comando npm install desde la línea de comandos. Por ejemplo, para agregar nuestra primera dependencia, solicitud, intente ejecutar esto:

1
$ npm install --save request

El comando install descargará el paquete request más reciente de npm y lo guardará en el directorio node_modules. Agregar el indicador --save le dice a npm que guarde los detalles del paquete en package.json en la sección 'dependencies':

1
2
3
"dependencies": {
    "request": "2.67.0"
}

Ahora podrá usar el módulo request en cualquier parte del código de su proyecto.

Mejorando el código

El módulo request le brinda funciones para realizar fácilmente todo tipo de solicitudes HTTP. El ejemplo de HTTP que mostramos arriba no fue tan malo, pero request hace que el código sea aún más compacto y fácil de leer. El código equivalente usando request se vería así:

1
2
3
4
5
6
var request = require('request');

request('http://ipinfo.io/json', function(error, response, body) {
    var json = JSON.parse(body);
    console.log('Your location: ' + json.city + ', ' + json.region);
});

Sería más interesante si pudiéramos encontrar la ubicación de cualquier dirección IP, y no solo la nuestra, así que permitamos que el usuario ingrese una dirección IP como argumento de línea de comando. Como esto:

1
$ node index.js 8.8.8.8

Para acceder a este argumento dentro de nuestro programa, Node lo pone a disposición en el objeto proceso global como proceso.argv, que es una matriz. Para el comando que acabamos de ejecutar arriba, process.argv sería ['node', 'index.js', '8.8.8.8'].

Para facilitar aún más las cosas, usaremos el paquete yargos para ayudarnos a analizar los argumentos de la línea de comandos. Con un programa simple como este, yargs no es realmente necesario, pero mejoraré twenty en un artículo posterior, por lo que también podríamos agregarlo ahora.

Al igual que request, lo instalaremos con:

1
$ npm install --save yargs

Modificando el código para usar yargs para tomar el argumento (o por defecto a nuestra propia IP si no se dio ningún argumento), terminamos con esto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var request = require('request');
var argv = require('yargs').argv;

var path = 'json';

path = argv._[0] || path;

request('http://ipinfo.io/' + path, function(error, response, body) {
    var json = JSON.parse(body);
    console.log('Server location: ' + json.city + ', ' + json.region);
});

Hasta ahora, esta herramienta es excelente para el uso de la línea de comandos, pero ¿qué pasa si alguien quiere usarla como una dependencia en su propio código? A partir de ahora, el código no se ha exportado, por lo que no podrá usarlo en ningún otro lugar que no sea la línea de comandos. Para decirle a Node qué funciones/variables debe tener disponibles, podemos usar module.exports.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var request = require('request');
var argv = require('yargs').argv;

var findLocation = function(ip, callback) {
    var path;
    if (typeof(ip) === 'function' || !ip) path = 'json';
    else path = ip;
    
    request('http://ipinfo.io/' + path, function(error, response, body) {
        var json = JSON.parse(body);
        callback(null, json.city + ', ' + json.region);
    });
};

module.exports = findLocation;

¡Excelente! Ahora cualquiera que descargue este paquete puede solicitarlo en cualquier parte de su código y usar la función findLocation().

Pero, es posible que haya notado que ahora ya no podemos usarlo como una herramienta de línea de comandos. Sin embargo, no queremos poner el resto del código anterior así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
var request = require('request');
var argv = require('yargs').argv;

var findLocation = function(ip, callback) {
    var path;
    if (typeof(ip) === 'function' || !ip) path = 'json';
    else path = ip;
    
    request('http://ipinfo.io/' + path, function(error, response, body) {
        var json = JSON.parse(body);
        callback(null, json.city + ', ' + json.region);
    });
};

var arg = argv._[0] || path;

// This runs every time the file is loaded
findLocation(arg, function(err, location) {
    console.log('Server location: ' + location);
});

module.exports = findLocation;

Esto sería malo porque cada vez que alguien ‘requiere()’ este archivo para usar la función ‘findLocation()’, imprimirá su propia ubicación en la línea de comando. Necesitamos una manera de determinar si este archivo fue llamado directamente con node index.js y no por require(), por lo que si fue llamado directamente, entonces revisaremos la línea de comando en busca de argumentos. Esto se puede hacer comparando require.main con module, así: if (require.main === module) {...}, lo que nos deja con:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
var request = require('request');
var argv = require('yargs').argv;

var findLocation = function(ip, callback) {
    var path;
    if (typeof(ip) === 'function' || !ip) path = 'json';
    else path = ip;
    
    request('http://ipinfo.io/' + path, function(error, response, body) {
        var json = JSON.parse(body);
        callback(null, json.city + ', ' + json.region);
    });
};

if (require.main === module) {
    findLocation(argv._[0], function(err, location) {
        console.log('Server location: ' + location);
    });
}

module.exports = findLocation;

Ahora podemos usar este código tanto en la línea de comandos y como una dependencia.

Nota: Hay una mejor manera de hacer el híbrido CLI/biblioteca, pero lo mantendremos simple y seguiremos con este método por ahora. Consulte veinte en Github para obtener más información, específicamente el directorio bin y la configuración de package.json.

Publicando su paquete

Finalmente, queremos que esté disponible para otros en npm. Todo lo que necesita hacer para que el paquete esté disponible es ejecutar esto en el directorio del paquete:

1
$ npm publish

Se le pedirá su nombre de usuario y contraseña, y luego el código se envía al registro.

Tenga en cuenta que necesitará alcance su paquete o cambiar su nombre, ya que yo ya tengo el nombre 'twenty'.

Dónde ir desde aquí

Con la popularidad de Node en auge, hay toneladas de recursos en Internet. Estos son algunos de los libros y cursos más populares que he encontrado, que le enseñarán mucho más de lo que pude mostrar aquí:

O si desea seguir con algunos tutoriales más cortos, aquí hay algunos de Stack Abuse que pueden ser útiles:

Solo tenga en cuenta que la gran mayoría de lo que aprenderá será de su propia exploración del lenguaje, las herramientas y los paquetes. Entonces, si bien artículos como este son buenos para comenzar, asegúrese de concentrarse más en escribir código que leer sobre alguien más escribiendo código. La experiencia triunfa sobre todo lo demás.

Conclusión

Solo cubrimos una pequeña fracción de lo que Node y npm tienen para ofrecer, así que consulte algunos de los recursos a los que me vinculé anteriormente para obtener más información.

Y no puedo enfatizar lo suficiente lo importante que es para ti obtener experiencia escribiendo código. npm hace que sea realmente fácil buscar paquetes y encontrar sus repositorios. Así que encuentre un paquete que sea útil o interesante para usted y vea cómo funciona debajo.

¿Eres un novato en Node? ¿Sobre qué otros temas de Node quieres aprender? ¡Cuéntanos en los comentarios! s!*