![](https://i.imgur.com/ld6aL74.png =200x) # Express | Introducción ## Introducción En esta lección, aprenderemos cómo un **framework** como Express puede ayudarnos a organizar nuestro código de back-end. Antes de que podamos entrar en las capacidades reales del back-end, primero debemos aprender cómo configurar un sitio web básico utilizando tecnologías de back-end. Eso es exactamente lo que aprenderemos aquí: **cómo hacer un sitio web básico** usando Node.js y Express. :::warning :warning: Este tipo de sitio web **no necesita Express ni back-end**. Sería mejor crear un sitio web como este con HTML, CSS y JavaScript simples y antiguos. Solo estamos creando estos sitios web simples para sentar las bases de cómo usar Express para que podamos realizar tareas de back-end más apropiadas más adelante. ::: ## Web Frameworks **¿Por qué usamos un *framework*?** Los [Web Frameworks](https://en.wikipedia.org/wiki/Web_framework) o web application framework (WAF) es un marco de software diseñado para respaldar el desarrollo de aplicaciones web, incluidos servicios web, recursos web y API web. Los frameworks web tienen como objetivo aliviar la sobrecarga asociada con las actividades comunes realizadas en el desarrollo web. Por ejemplo, muchos frameworks web nos brindan: - **Bibliotecas para el acceso a la base de datos** (para guardar sus datos de forma permanente) - **Plantillas de frameworks** (para hacer HTML dinámico que cambia entre usuarios) - **Gestión de sesiones** (para realizar un seguimiento de los usuarios) - **A menudo promueve la reutilización del código** Aunque a menudo se dirigen al desarrollo de sitios web dinámicos, también son aplicables a sitios web estáticos. Podemos construir una aplicación web completa usando solo Node.js, Ruby, Python o cualquier otro lenguaje de backend. Sin embargo, con el tiempo, la gente ha desarrollado *frameworks* sobre estos diferentes lenguajes por algunas razones: - Hacemos muchas de las tareas mencionadas anteriormente para *cada* aplicación web, y es tedioso de configurar. - Necesitamos una forma de estructurar nuestro código, toda nuestra lógica compleja puede acumularse con el tiempo, dejándonos con un lío. - Nos beneficiamos del trabajo de otras personas. Si estás utilizando tu propio framework, todos los errores son tuyos para corregirlos. Con una comunidad que rodea el framework, recibimos ayuda en este sentido. ### Express Web Framework ![](https://i.imgur.com/T9ARM9m.png) [ExpressJS](http://expressjs.com/) es el *framework* más utilizado en el ecosistema Node.js. Todos los programadores de Node.js han oído hablar de él y lo están usando con o sin darse cuenta. Hay bastantes [frameworks Node.js](http://expressjs.com/en/resources/frameworks.html) construidos en base a él o inspirados en sus conceptos. Express.js, o simplemente Express, es una aplicación framework para Node.js, lanzada como software gratuito y de código abierto bajo la licencia MIT. Está diseñado para crear aplicaciones web y API. Es el servidor *framework* estándar de facto para Node.js. El autor original lo describió como relativamente mínimo con muchas características disponibles como complementos. Express es la parte de backend del stack *MEAN*, junto con la base de datos MongoDB y el frontend Angular. ## Más HTTP - Verbos HTTP Antes de entrar en nuestro primer código Express, necesitamos profundizar un poco en nuestro conocimiento de HTTP. Necesitamos hablar sobre algo llamado **verbos HTTP**. Cuando un cliente envía una solicitud HTTP a un servidor, además de especificar la URL, el cliente también tiene que especificar un fragmento de texto adicional llamado **verbo HTTP** (también conocido como método _HTTP_). Este **verbo HTTP** debe formar parte de una lista de palabras válidas en la especificación HTTP. Los verbos están diseñados para que los clientes **comuniquen la intención de la solicitud** a los servidores. El software de los servidores está programado para considerar el verbo al decidir qué hacer con una solicitud. Los dos verbos más comunes son "GET" y "POST". La mayoría de las solicitudes que su navegador realiza a diario son solicitudes "GET", para recuperar algún tipo de información. Por ejemplo, hacemos una solicitud `GET` a` https://www.netflix.com/navegar`, y el servidor nos devuelve una página HTML. El servidor decide si es posible una solicitud con ese verbo y esa URL. Necesitamos conocer estos verbos porque cuando programamos nuestro propio back-end, decidimos qué **verbos HTTP** funcionan con qué URL. ### `GET` Peticiones `GET`: - Debe usarse solo para recuperar datos de un servidor - Puede almacenarse en caché - Permanecer en el historial del navegador - Se pueden marcar como favoritas - Nunca debe usarse para enviar datos confidenciales - Tiene restricciones de longitud (no puede enviar archivos gigantes) **Ejemplo** Escribimos google.com en la barra de URL y presionamos enter. ¡Acabamos de hacer una solicitud **"GET"**! ### `POST` Una petición `POST` es para *enviar data o información al servidor.* Peticiones `POST`: - Debe usarse para enviar datos al servidor - Nunca se almacenan en caché - No se quedan en el historial del navegador - No se pueden marcar como favoritas - Son mejores para datos confidenciales - No tenga restricciones en la longitud de los datos (puede enviar archivos grandes) **Ejemplo** Cuando ingresa información en un formulario de inicio de sesión en Facebook y presiona enviar, está haciendo un "POST". Le está diciendo a los servidores de Facebook: "Aquí está mi información de inicio de sesión, inicie sesión por favor". Además, al realizar transacciones bancarias, a menudo se manejan a través de solicitudes "POST". Esto es para evitar que retires (o acredites) dinero una y otra vez al repetir transacciones accidentalmente. ## Express Hello World [ExpressJS](http://expressjs.com/) es un framework web construido sobre Node.js que tiene funciones que se asemejan mucho al proceso de solicitud-respuesta. Configuremos nuestra primera aplicación Express. **1 |** Creamos una carpeta que se llame `express-hello-world`. ```bash $ mkdir express-hello-world $ cd express-hello-world ``` **2 |** Instalamos **Express** con NPM y lo guardamos como una dependencia en nuestro proyecto, luego creamos un archivo para ejecutar nuestro *servidor* llamado `app.js` ```bash $ npm init (Hit return until prompted to type "yes") $ npm install express --save $ touch app.js ``` **3 |** Escribimos nuestro servidor `app.js` Primero debemos requerir Express para poder usarlo en nuestra aplicación. La función [express()](https://expressjs.com/en/4x/api.html#express) crea una [Aplicación Express](https://expressjs.com/en/4x/api.html#app ). ```javascript= const express = require('express'); // We create our own server named app // Express server handling requests and responses const app = express(); ``` **4 |** Creamos una ruta Las aplicaciones web tienen muchas páginas diferentes y necesitamos decirle a nuestro servidor qué hacer cuando recibe una solicitud. Normalmente, un servidor identifica las solicitudes con dos parámetros: - **URLs** En back-end, solo consideramos la parte de la URL que viene después del dominio. Ejemplos: - Si la URL completa es [example.com/profile](http://example.com/profile) nos referimos a la misma como `/profile` - Si la URL completa es [example.com/blogs](http://example.com/blogs) nos referimos a la misma como `/blogs` - Si la URL completa es [example.com](http://example.com) nos referimos a la misma como `/` - **Método HTTP**: `get` Por ahora, nos ceñiremos a las solicitudes `GET`. Hablaremos más sobre `POST` en una lección posterior. ```javascript= const express = require('express'); const app = express(); // our first Route app.get('/', (request, response, next) => { console.log(request); response.send('<h1>Welcome Ironhacker. :)</h1>'); }); ``` Es importante destacar que cada ruta aceptará una *devolución de llamada*. Esta es la función a la que se llamará cuando alguien haga una solicitud a `/`. - **app**: Nuestro servido Express - **`get`**: El **método HTTP** necesario para acceder a esta URL - **`/`**: la ruta que el usuario escribirá en la barra de URL - `request`: Un * objeto * que contiene información sobre la solicitud, como los encabezados. Veremos más sobre esto más adelante. - `response`: Un * objeto * que contiene información sobre la respuesta, como encabezados y cualquier dato que necesitemos enviar al cliente. - `next`: Función que se utiliza para gestionar errores y otros procesos. Los tres parámetros de `request`,` response` y `next` siempre se pasarán a la función de devolución de llamada para cualquier ruta. El objeto `response` tiene métodos que nos permiten controlar lo que enviamos al cliente. En este caso, estamos usando el método `send()` que solo envía una cadena. **5 |** Arrancamos el servidor! Le decimos a nuestro servidor que *escuche continuamente las solicitudes* en el puerto 3000. Opcionalmente, podemos proporcionar un *callback* para hacer algo una vez que se configura la escucha. ```javascript=12 // Server Started app.listen(3000, () => { console.log('My first app listening on port 3000!') }); ``` **Nuestro primer código Express** ```javascript= // Require Express const express = require('express'); // Express server handling requests and responses const app = express(); // our first Route: app.get('/', (request, response, next) => { response.send('<h1>Welcome Ironhacker. :)</h1>'); }); // Server Started app.listen(3000, () => { console.log('My first app listening on port 3000!'); }); ``` Para ver la aplicación web, debemos ejecutar el servidor con Node. Recordamos que debido a que ejecutamos `app.listen ()`, el programa se ejecutará hasta que lo detengamos manualmente. ```shell $ node app.js ``` Nos vamos a [localhost:3000](http://localhost:3000)! :::info :bulb: Para parar el servidor, apretamos `CONTROL`+`C` en la terminal ::: ## nodemon Estamos a punto de realizar muchos cambios en el archivo `app.js`. Cada vez que cambia algo en el programa servidor, tenemos que detenerlo con `CONTROL + C` y ejecutarlo nuevamente con` node app.js`. Vamos a ver que podemos hacer para eso! Hay otro paquete npm impresionante llamado [**nodemon**](https://nodemon.io/) que puede ayudarnos a recargar nuestra aplicación automáticamente cada vez que guardamos un cambio en nuestro JavaScript. Primero, comencemos por instalarlo: ```shell $ npm install nodemon --global ``` Estamos instalando **nodemon** con la opción `--global`, lo que significa que lo estamos instalando como un comando en la terminal. Esto nos permitirá ejecutar nuestra aplicación usando el comando `nodemon` en lugar de` node`. ```shell $ nodemon app.js ``` Una vez que tenga la `app.js` ejecutándose con **nodemon**, verá que se recarga automáticamente en la terminal **cada vez que guarde**. ¡Ya no es necesario parar con `CONTROL + C`! ## Archivos estáticos Los archivos estáticos son cosas como imágenes, CSS y JavaScript del lado del cliente que se envían directamente desde el servidor al navegador tal cual. Express tiene soporte incorporado para servir este tipo de archivos. Normalmente, estos archivos se guardan en una carpeta llamada `public`: ``` $ mkdir public ``` Creemos una carpeta para imágenes y descarguemos una imagen en esa carpeta: ``` $ mkdir public/images $ curl -o public/images/cool-cat.jpg https://wallpapercave.com/wp/X7VjxFk.jpg ``` Dentro de Express, tenemos que decirle a nuestro servidor que sirva archivos estáticos desde el directorio `public`: ```javascript=4 // ... const app = express(); // Make everything inside of public/ available app.use(express.static('public')); ``` Si visitamos [localhost:3000/images/cool-cat.jpg](http://localhost:3000/images/cool-cat.jpg) veremos la imagen! Tengamos en cuenta que la URL **no incluye la parte `public`**. Esto es importante cuando vincula su HTML a estos archivos externos. Uno de los beneficios de usar archivos estáticos es que podemos incorporarlos en nuestro HTML para que el navegador los lea. **Crear una hoja de estilo:** ``` $ mkdir public/stylesheets $ touch public/stylesheets/style.css ``` **Y el siguiente código a `style.css`:** ```css= body { color: blue; background-color: bisque; } ``` **Creamos una nueva ruta:** ```javascript // ... app.get('/cat', (request, response, next) => { response.send(` <!doctype html> <html> <head> <meta charset="utf-8"> <title>Cat</title> <link rel="stylesheet" href="/stylesheets/style.css" /> </head> <body> <h1>Cat</h1> <p>This is my second route</p> <img src="/images/cool-cat.jpg" /> </body> </html> `); }); // ... ``` Y visitamos [localhost:3000/cat](http://localhost:3000/cat)! Nuevamente, observamos las URL que usamos al vincular a estos archivos: 1. `public/images/cool-cat.jpg` está linkeada como `/images/cool-cat.jpg` 2. `public/stylesheets/style.css` está linkeada como `/stylesheets/style.css` **Linkeando archivos estáticos** Algunos **puntos importantes** que tenemos que tener en cuenta cuando linkeamos archivos estáticos en Express: - No incluimos la parte `public` - Siempre empezamos el link con `/` - Nunca ponemos la raíz [localhost:3000](http://localhost:3000) ### Flujo de solicitud-respuesta de archivos estáticos ![](https://s3-eu-west-1.amazonaws.com/ih-materials/uploads/upload_e9728aae585f81940c61289c0125f9f2.png) ## HTML Separado En el ejemplo anterior, comenzamos a agregar una estructura HTML más realista a nuestro método `send()`. Como podemos ver, puede resultar muy complicado poner un montón de HTML dentro de una cadena de JavaScript. Tiene algunas desventajas: 1. **Mala legibilidad**: hace que nuestras rutas sean _muy_ largas, lo que dificulta su lectura. 2. **Sin opciones de sintaxis**: no nos beneficiamos del resaltado de sintaxis y los fragmentos que obtenemos en un archivo HTML. 3. **Mala separación de partes** - En última instancia, queremos separar la lógica de nuestro back-end (las rutas y su funcionalidad) de la apariencia de nuestra aplicación (el HTML y CSS que ven los usuarios). En este caso, mezclar los dos conduce a un código incorrecto. Para resolver estos problemas, tenemos la capacidad de crear archivos HTML separados para el contenido de cada una de nuestras páginas. Comenzamos creando una carpeta para nuestros archivos HTML y luego los propios archivos. ```shell $ mkdir views $ touch views/home-page.html $ touch views/cat-page.html ``` :::info :bulb: En este caso, `views/` se refiere al **código de presentación**, el código que ven los usuarios (de ahí el término _views_). ::: - El archivo `home-page.html` va a mostrar el contenido de la ruta `/`. - El archivo `cat-page.html` va a mostrar el contenido de la ruta `/cat`. Empezamos con `home-page.html`: ```htmlmixed= <!doctype html> <html> <head> <meta charset="utf-8"> <title>Bienvenida</title> <link rel="stylesheet" href="/stylesheets/style.css" /> </head> <body> <h1>Bienvenido a la primera página. :)</h1> <a href="/cat">Ver Cat Page</a> </body> </html> ``` Ahora `cat-page.html`: ```htmlmixed= <!doctype html> <html> <head> <meta charset="utf-8"> <title>Cat</title> <link rel="stylesheet" href="/stylesheets/style.css" /> </head> <body> <h1>Cat</h1> <p>This is my second route</p> <img src="/images/cool-cat.jpg" /> <a href="/">Volver a la Home</a> </body> </html> ``` Vemos que estamos linkeando las páginas de la siguiente forma: - `/` para la Home - `/cat` para la Cat Page. ¿Cómo se conectan los archivos HTML a las rutas? Ese es nuestro próximo cambio. En `app.js` modificamos nuestras dos rutas para hacer referencia a los archivos HTML: ```javascript=10 // ... // our first Route: app.get('/', (request, response, next) => { response.sendFile(__dirname + '/views/home-page.html'); }); // cat route: app.get('/cat', (request, response, next) => { response.sendFile(__dirname + '/views/cat-page.html'); }); // ... ``` - Aquí estamos usando un nuevo método de `response`:` sendFile()`. El método `sendFile()` nos permite responder con el contenido de un archivo. Es una alternativa a `send()` que solo nos permite enviar una cadena directamente. - `__dirname` (dos guiones bajos) se refiere a la carpeta en la que se encuentra nuestro` app.js`. Intente `console.log (__ dirname)` para que pueda ver su valor. Si no especificamos la **ruta completa al archivo HTML**, nuestro `sendFile ()` fallará. :::danger :rotating_light: No confundamos entre el nombre del archivo HTML y la URL. **La URL está determinada por la ruta**: `app.get ('/ cat', ...)` significa que debemos ir a [localhost:3000/cat](http://localhost:3000/cat). A través de la `response` nos conectamos a la URL de la ruta al archivo HTML: `response.sendFile(__dirname + 'views/cat-page.html');`. :electric_plug: Hacer estas conexiones es de lo que se trata el back-end. ::: :::info :zap: ¿No podríamos haber colocado los archivos HTML en `public/` y referirnos a ellos directamente como [localhost:3000/cat-page.html](http://localhost:3000/cat-page.html)? ¡Sí! Pero veremos más adelante que esta estructura de hacer que la **ruta se refiera al HTML** será útil más adelante. ::: La versión final de nuestra aplicación Express `app.js`: ```javascript= // Require Express const express = require('express'); // Express server handling requests and responses const app = express(); // Make everything inside of public/ available app.use(express.static('public')); // our first Route: app.get('/', (request, response, next) => { response.sendFile(__dirname + '/views/home-page.html'); }); // cat route: app.get('/cat', (request, response, next) => { response.sendFile(__dirname + '/views/cat-page.html'); }); // Server Started app.listen(3000, () => { console.log('My first app listening on port 3000!'); }); ``` ## Recursos Extra - [Express Getting Started](https://expressjs.com/en/starter/installing.html) - [Express Hello World](https://expressjs.com/en/starter/hello-world.html) - [What is HTTP(video)](https://www.youtube.com/watch?v=eesqK59rhGA) - [HTTP Made Really Easy](https://www.jmarshall.com/easy/http/) - [A Beginner’s Guide to HTTP and REST](https://code.tutsplus.com/tutorials/a-beginners-guide-to-http-and-rest--net-16340)