¿Cómo implementar Node.js con Heroku o Docker? Parte 2

En esta segunda parte vamos a indagar mas acerca de cómo podemos implementar Node.js con Heroku, para que así puedas realizar tu propia aplicación y llevar a cabo tus proyectos usando estas poderosas herramientas. Si te perdiste la primera parte, checa esto: ¿Cómo implementar Node.js con Heroku o Docker? Parte 1

Declarando dependencias de la aplicación

Heroku reconoce una aplicación como Node.js por la existencia de un archivo llamado package.json en el directorio raíz.

Para tus propias aplicaciones, puede crear una ejecutando el siguiente comando: npm init --yes.

La aplicación de demostración que implementó ya tiene un package.json, y se parece a esto:


{
"name": "node-js-getting-started",
"version": "0.3.0",
...
"engines": {
"node": "8.11.1"
},
"dependencies": {
"ejs": "^2.5.6",
"express": "^4.15.2"
},
...
}

El archivo package.json determina tanto la versión de Node.js que se usará para ejecutar tu aplicación en Heroku, como las dependencias que deben instalarse con su aplicación.

Cuando se implementa una aplicación, Heroku lee este archivo e instala la versión de Node adecuada junto con las dependencias mediante el comando npm install.

Ejecuta este comando en tu directorio local para instalar las dependencias, esto va a  su sistema para ejecutar la aplicación localmente:

$ npm install
added 132 packages in 3.368s

Una vez que se instalan las dependencias, estarás listo para ejecutar tu aplicación localmente.

Ejecutando la aplicación localmente

Ahora debes iniciar tu aplicación localmente usando el siguiente comando heroku local, el cual se instaló como parte de la CLI de Heroku:

$ heroku local web
[OKAY] Loaded ENV .env File as KEY=VALUE Format
1:23:15 PM web.1 | Node app is running on port 5000

Al igual que Heroku, heroku local examina el Procfile para determinar qué ejecutar.

Luego abre la dirección http://localhost:5000 en tu navegador web de preferencia. Deberías ver tu aplicación ejecutándose de forma local.

Si quieres evitar que la aplicación se ejecute localmente, en la CLI, presione Ctrl+C para salir.

Realizar cambios locales

En este paso, aprenderás fácilmente cómo propagar un cambio local a tu aplicación a través de Heroku. Como ejemplo, modificarás la aplicación para agregar una dependencia adicional y el código para usarla.

Comienza añadiendo una dependencia para cool-ascii-faces en el paquete.json. Para ello, ejecuta el siguiente comando:

$ npm install cool-ascii-faces
+ cool-ascii-faces@1.3.4
added 9 packages in 2.027s

Debes modificar index.js para que requiera este módulo al inicio. También agrega una nueva ruta (/cool) que la utilice. Tu código final debería verse así:

const cool = require('cool-ascii-faces')
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000

express()
.use(express.static(path.join(__dirname, 'public')))
.set('views', path.join(__dirname, 'views'))
.set('view engine', 'ejs')
.get('/', (req, res) => res.render('pages/index'))
.get('/cool', (req, res) => res.send(cool()))
.listen(PORT, () => console.log(`Listening on ${ PORT }`))

Ahora prueba localmente:

$ npm install
$ heroku local

Visitando tu aplicación en http://localhost:5000/cool, deberías ver caras bonitas en cada actualización: ( ⚆ _ ⚆ ). 🤗

Ahora desplieguen. Casi todos los despliegues en Heroku siguen el mismo patrón. Primero, agregue los archivos modificados al repositorio git local:


$ git add .

Ahora confirma los cambios en el repositorio:


$ git commit -m "Add cool face API"

Ahora desplieguen, tal como lo se hizo antes:


$ git push heroku master

Por último, comprueba que todo funciona:


$  heroku open cool

Finalmente deberías ver otra cara. 😉

Complementos de provisión

Los complementos, son servicios cloud de terceros que proporcionan servicios adicionales listos para usar para su aplicación, desde la persistencia, pasando por el registro, la monitorización y mucho más.

Por defecto, Heroku almacena 1500 líneas de registros de tu aplicación. Sin embargo, hace que el flujo de registro completo esté disponible como un servicio, y varios proveedores adicionales han escrito servicios de registro que proporcionan cosas como la persistencia de registros, búsqueda y alertas por correo electrónico y SMS.

En este paso tú proveerás uno de estos complementos de registro, llamado Papertrail.

Este es el código para la provisión del complemento para el registro del Papertrail:


$ heroku addons:create papertrail
Adding papertrail on sharp-rain-871... done, v4 (free)
Welcome to Papertrail. Questions and ideas are welcome (support@papertrailapp.com). Happy logging!
Use `heroku addons:docs papertrail` to view documentation.

Para ayudar a prevenir el abuso, el aprovisionamiento de un complemento requiere la verificación de la cuenta. Si tu cuenta no ha sido verificada, se le indicará que visite el sitio de verificación.

Ahora el complemento ya está implementado y configurado para tu aplicación. Puedes hacer una lista de complementos para tu aplicación de esta manera:


$ heroku addons

Para ver este complemento en acción, visita la URL de Heroku de tu aplicación unas cuantas veces. Cada visita generará más mensajes de registro, que ahora deberían ser enviados al complemento del Papertrail. Visita la consola del Papertrail para ver los mensajes de registro, este es el código:


$ heroku addons:open papertrail

Su navegador abrirá una consola web Papertrail, mostrando los últimos eventos de registro. La interfaz le permite buscar y configurar alertas:

Alertas
Alertas

Comenzando una consola

Para tener una idea real del funcionamiento de los bancos de potencia, puedes crear otro banco de potencia único y ejecutar el comando bash, que abre una shell en ese banco de potencia.

A continuación, puedes ejecutar comandos allí. Cada banco de potencia tiene su propio espacio de archivos efímero, poblado con su aplicación y sus dependencias – una vez que el comando se completa (en este caso, bash), el banco de potencia se elimina.


$ heroku run bash
Running 'bash' attached to terminal... up, run.3052
~ $ ls
Procfile README.md composer.json composer.lock vendor views web
~ $ exit
exit

Si recibe un error, Error connecting to process, es posible que tengas que configurar tu cortafuegos.

No olvides escribir exit para salir del shell y terminar el banco de potencia.

Definir vars de configuración

Heroku le permite externalizar la configuración, almacenando datos como claves de encriptación o direcciones de recursos externos en config vars.

En tiempo de ejecución, los vars de configuración se exponen como variables de entorno a la aplicación. Por ejemplo, modificar index.js para que introduzca una nueva ruta, /times, que repita una acción en función del valor de la variable de entorno TIMES:

app.get('/times', (req, res) => {
let result = ''
const times = process.env.TIMES || 5
for (i = 0; i < times; i++) {
result += i + ' '
}
res.send(result)
})

heroku local configurará automáticamente el entorno basado en el contenido del archivo .env en tu directorio local. En el directorio superior de tu proyecto ya existe un archivo .env que contiene los siguientes contenidos:


TIMES=2

Si ejecutas la aplicación con heroku local, verás que se generan dos números cada vez.

Para configurar el config var en Heroku, ejecuta lo siguiente:


heroku config:set TIMES=2

Luego podrás ver los config vars que se configuran usando heroku config:

$ heroku config
== sharp-rain-871 Config Vars
PAPERTRAIL_API_TOKEN: erdKhPeeeehIcdfY7ne
TIMES: 2

Despliega tu aplicación modificada en Heroku y luego visítala ejecutando heroku open times.

Realizando la base de datos

El mercado de complementos tiene una gran cantidad de almacenes de datos, desde los proveedores de Redis y MongoDB hasta Postgres y MySQL. En este paso, agregará una base de datos de desarrollo gratuita de Heroku Postgres Starter Tier a su aplicación.

Agrega la base de datos:


$ heroku addons:create heroku-postgresql:hobby-dev
Adding heroku-postgresql:hobby-dev... done, v3 (free)

Esto crea una base de datos y establece una variable DATABASE_URL de entorno (puede verificar esto ejecutando el comando heroku config).

Úsa el comando npm para instalar el módulo pg a tus dependencias:

$ npm install pg
+ pg@7.4.3
added 14 packages in 2.108s

"dependencies": {
"cool-ascii-faces": "^1.3.4",
"ejs": "^2.5.6",
"express": "^4.15.2",
"pg": "^7.4.3"
},

Ahora edita su archivo index.js para usar este módulo para conectarse a la base de datos especificada en tu variable de entorno DATABASE_URL. Agrega esto cerca de la parte superior:
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: true
});

Ahora agrega otra ruta,agregando lo siguiente: /db justo después de la existente .get(‘/’, …) como se muestra en el ejemplo:
.get('/db', async (req, res) => {
try {
const client = await pool.connect()
const result = await client.query('SELECT * FROM test_table');
const results = { 'results': (result) ? result.rows : null};
res.render('pages/db', results );
client.release();
} catch (err) {
console.error(err);
res.send("Error " + err);
}
})

Esto garantiza que cuando acceda a tu aplicación utilizando la ruta /db, devolverá todas las filas de la tabla test_table.

Despliega esto a Heroku. Si accedes a /db, recibirás un error ya que no hay ninguna tabla en la base de datos. Suponiendo que tienes Postgres instalado localmente, usa el comando heroku pg:psql para conectarse a la base de datos remota, crea una tabla e inserte una fila:

$ heroku pg:psql
psql (9.5.2, server 9.6.2)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
=> create table test_table (id integer, name text);
CREATE TABLE
=> insert into test_table values (1, 'hello database');
INSERT 0 1
=> \q

¡Felicidades por haber completado esta lección! 🏅🏆🥇