====== Desarrollo de aplicaciones: backend + frontend ======
{{ frontendbackend.jpg }} Frontend vs Backend (Fuente: https://ecdisis.com/que-es-frontend-y-backend/)
===== Configuración del proyecto ===== Crear un fichero [[https://docs.npmjs.com/creating-a-package-json-file|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 fichero ''package.json'' de forma interactiva (si se añade ''--yes'' se rellenará directamente con valores por defecto) * ''npm run'': Lista los scripts disponibles * ''npm run [[https://docs.npmjs.com/cli/v10/configuring-npm/package-json|Especificación completa para el fichero package.json]] ===== 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? ====
{{ web_api.png }} Web API (Fuente: https://www.programmingwithmukesh.com/articles/web-api)
{{ urls.png }} Tipos de operaciones en una Web 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
{{ sample1-cities.png }} Listado de todas las ciudades
* 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)
{{ sample1-city.png }} Detalles de una ciudad concreta
También podemos utilizar aplicaciones como [[https://hoppscotch.com/|Hoppscotch]] que son específicas para desarrolladores. Son clientes diseñados para realizar llamadas a APIs y testear que éstas funcionan correctamente.
{{ hoppscotch.png }} Hoppscotch
===== 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" } } Ejemplo 1: API con Node.js

Ejemplo de API con Node.js

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
{{ cities-frontend.png }} cities-frontend
===== 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 [[https://en.wikipedia.org/wiki/Create,_read,_update_and_delete|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 [[https://entornos-desarrollo.codeandcoke.com/_detail/apuntes:urls.png?id=apuntes%3Abackend_frontend|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 ==== Ejemplo 1: API con Node.js

Ejemplo de API con Node.js


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 };
{{ cities-frontend-crud.png }} cities-frontend-crud
====== Proyectos de ejemplo ====== Todos los proyectos de ejemplo de esta parte están en el repositorio [[https://github.com/codeandcoke/nodejs|nodejs]] de GitHub. ---- (c) 2024 Santiago Faci