Table of Contents
Desarrollo de aplicaciones: backend + frontend
Configuración del proyecto
Crear un fichero package.json:
{ "name": "cities-backend", "version": "0.1", "description": "A sample project to learn Node.js", "type": "module", "scripts": { "start": "node src/app.js" }, "author": "Santiago Faci", "license": "GPL-2.0-only", "dependencies": { "express": "^4.21.1" } }
Algunos comandos útiles:
npm init
: Crear un ficheropackage.json
de forma interactiva (si se añade–yes
se rellenará directamente con valores por defecto)npm run
: Lista los scripts disponiblesnpm run <nombre_script
: Ejecuta el script cuyo nombre se para como parámetronpm start
: Ejecuta el scriptstart
(se puede ejecutar sin añadirrun
al tratarse de uno de los scripts definidos por nodejs)
Gestión de dependencias
Añadir las dependencias necesarias para el proyecto al fichero package.json
en la sección dependencies
(se pueden ir añadiendo a medida que son necesarias durante el desarrollo del proyecto):
. . . "dependencies": { "express": "^4.21.1" } . . .
Instalar todas las dependencias necesarias para el proyecto:
npm install
Actualizar las dependencias necesarias para el proyecto, si es necesario:
npm update
También se pueden instalar una dependencia concreta y ésta será añadida automáticamente al fichero package.json
como tal:
npm install express
Backend
¿Qué es una API?
API sencilla sólo lectura
import express from 'express'; const app = express(); app.use(express.json()); const cities = { 'Zaragoza': { altitude: 199, population: 673010 }, 'Huesca': { altitude: 488, population: 53305 }, 'Teruel': { altitude: 915, population: 25900 } }; app.get('/cities', (req, res) => { res.json(cities); }); app.get('/city/:city', (req, res) => { const city = req.params.city; res.json(cities[city]); }); app.listen(8080, () => { console.log('Iniciando el backend en el puerto 8080'); });
Asumiendo que tenemos un fichero package.json
como el explicado anteriormente, podremos ejecutar la API con el siguiente comando:
npm start
Y tendremos los siguiente endpoints disponibles:
- http://localhost:8080/cities: Para ver el listado de todas las ciudades en formato JSON
- http://localhost:8080/city/Zaragoza: Para ver los datos de una ciudad concreta (en este caso Zaragoza pero podríamos indicar cualquiera de las existentes)
También podemos utilizar aplicaciones como Hoppscotch que son específicas para desarrolladores. Son clientes diseñados para realizar llamadas a APIs y testear que éstas funcionan correctamente.
Frontend
{ "name": "cities-frontend", "version": "0.1", "source": "src/index.html", "type": "module", "scripts": { "start": "parcel --no-cache", "build": "parcel build" }, "devDependencies": { "buffer": "^6.0.3", "parcel": "latest", "process": "^0.11.10" }, "dependencies": { "axios": "^1.7.7" } }
<!DOCTYPE html> <html> <head> <title>Ejemplo 1: API con Node.js</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <script type="module" src="app.js"></script> </head> <body onload="readCities()"> <div class="container"> <h1>Ejemplo de API con Node.js</h1> <img src="nodejs.png"/> <ul id="cities" class="list-group"> </ul> </div> </body> </html>
import axios from 'axios'; function addCityNode(name) { const citiesUl = document.getElementById('cities'); const item = document.createElement('li'); item.className = 'list-group-item'; item.appendChild(document.createTextNode(name)); citiesUl.appendChild(item); }; window.readCities = function() { axios.get('http://localhost:8080/cities') .then((response) => { const cityList = response.data; Object.keys(cityList).forEach(cityName => { addCityNode(cityName); }); }); };
Tal y como hacemos con el backend, podremos ejecutar este frontend con el siguiente comando:
npm start
Hay que tener en cuenta que backend y frontend debes escuchar en puertos diferentes para poder ejecutarse al mismo tiempo. En nuestro caso el backend escucha en el puerto 8080 y el frontend en el 1234
CRUD Backend + Frontend
Una vez que hemos visto una sencilla API con unicamente un par de operaciones de lectura, vamos a ver un ejemplo algo más completo. Es lo que también se conoce como CRUD que es el acrónimo que se utiliza para referirse a las 4 operaciones básica que permite que los usuarios puedan registrar (Create), leer (Read), modificar (Update) y borrar (Delete) información utilizando algún tipo de software.
En el caso de la API (backend) deberán ser diseñadas conforme a las convenciones que vimos un poco antes cuando explicamos lo que era una API.
Backend
import express from 'express'; import cors from 'cors'; const app = express(); app.use(cors()); app.use(express.json()); const cities = { 'Zaragoza': { altitude: 199, population: 673010 }, 'Huesca': { altitude: 488, population: 53305 }, 'Teruel': { altitude: 915, population: 25900 } }; app.get('/cities', (req, res) => { res.json(cities); }); app.get('/city/:city', (req, res) => { const city = req.params.city; res.json(cities[city]); }); app.post('/cities', (req, res) => { const name = req.body.name; const altitudeValue = req.body.altitude; const populationValue = req.body.population; cities[name] = { altitude: altitudeValue, population: populationValue }; console.log(cities); res.status(201).end(); }); app.listen(8080, () => { console.log('Iniciando el backend en el puerto 8080'); });
Frontend
<!DOCTYPE html> <html> <head> <title>Ejemplo 1: API con Node.js</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <script type="module" src="app.js"></script> </head> <body onload="readCities()"> <div class="container"> <h1>Ejemplo de API con Node.js</h1> <img src="nodejs.png"/> <ul id="cities" class="list-group"> </ul> <hr/> <form> <div class="mb-3"> <label for="name" class="form-label">Nombre</label> <input class="form-control" type="text" id="name"/> </div> <div class="mb-3"> <label for="altitude" class="form-label">Altitud</label> <input class="form-control" type="text" id="altitude"/> </div> <div class="mb-3"> <label for="population" class="form-label">Población</label> <input class="form-control" type="text" id="population"/> </div> <button type="button" class="btn btn-primary" onClick="addCity()">Add city</button> </form> </div> </body> </html>
import axios from 'axios'; function addCityNode(name) { const citiesUl = document.getElementById('cities'); const item = document.createElement('li'); item.className = 'list-group-item'; item.appendChild(document.createTextNode(name)); const button = document.createElement('button'); button.className = 'btn-close' button.onclick = function() { removeCity(name); item.remove(); }; item.appendChild(button); citiesUl.appendChild(item); }; window.readCities = function() { axios.get('http://localhost:8080/cities') .then((response) => { const cityList = response.data; Object.keys(cityList).forEach(cityName => { addCityNode(cityName); }); }); }; window.addCity = function() { const name = document.getElementById('name').value; const altitude = document.getElementById('altitude').value; const population = document.getElementById('population').value; if (name === '') { alert('El nombre es un campo obligatorio'); return; } axios.post('http://localhost:8080/cities', { name: name, altitude: altitude, population: population }).then(() => { addCityNode(name); }); }; window.removeCity = function(name) { console.log(name + ' was removed'); // TODO Remove the city };
Proyectos de ejemplo
Todos los proyectos de ejemplo de esta parte están en el repositorio nodejs de GitHub.
© 2024 Santiago Faci