En el desarrollo de software moderno, la arquitectura de Aplicación de Una Sola Página (SPA) desacoplada se ha convertido en el estándar de la industria. Este enfoque permite crear interfaces fluidas y rápidas, similares a aplicaciones de escritorio, mediante la separación total entre la interfaz visual y el servidor de datos.

En este proyecto se desarrolló un Sistema de Gestión de Inventario utilizando React + Vite para el frontend y Node.js + Express para el backend, comunicándose mediante una API REST para realizar operaciones CRUD en tiempo real.


🏛️ El Problema: Interfaces Lentas y Código Acoplado

Las aplicaciones web tradicionales recargaban la página completa tras cada acción del usuario, generando diversos inconvenientes:

  • Latencias perceptibles.
  • Consumo innecesario de ancho de banda.
  • Experiencia de usuario poco fluida.
  • Código monolítico difícil de escalar y mantener.

Estas limitaciones motivan la adopción de arquitecturas desacopladas capaces de ofrecer una experiencia más cercana a una aplicación de escritorio.


🚀 La Solución: Desacoplamiento de Servicios

La arquitectura SPA divide la aplicación en dos componentes independientes que se comunican de forma asíncrona.

Frontend (React)

Responsable del renderizado y la interacción con el usuario directamente en el navegador.

Backend (Express)

Servidor ligero encargado de gestionar la lógica de negocio y exponer endpoints REST.

Comunicación (Fetch API)

Permite intercambiar información entre frontend y backend sin necesidad de recargar la página.

Vista de la Interfaz Principal del Dashboard

A continuación se muestra el dashboard empresarial con analíticas calculadas dinámicamente en tiempo real.

Figura 1. Dashboard Principal del Sistema

Dashboard de Inventario SPA

🔑 Pilares de la Implementación

Para garantizar una arquitectura sólida y escalable, se emplean los siguientes fundamentos.

CORS

Configuración de seguridad necesaria para permitir la comunicación entre diferentes orígenes (por ejemplo, los puertos 5173 y 5000).

Estado Reactivo con useState

Gestión inmutable de datos que permite actualizar automáticamente la interfaz cuando cambia el estado.

Control de Efectos con useEffect

Sincroniza el ciclo de vida de los componentes con operaciones externas, como la carga de datos desde el servidor.

UX Premium

Implementación de métricas automáticas, alertas de stock bajo y modales personalizados para mejorar la experiencia del usuario.


🛠️ Desarrollo: Implementación Paso a Paso

Paso 1: Configuración del Servidor Backend

Se implementó un servidor Express con una base de datos temporal en memoria y endpoints REST para realizar operaciones CRUD.

Código Principal del Backend

const express = require('express');
const cors = require('cors');

const app = express();
const PORT = 5000;

app.use(cors());
app.use(express.json());

let productos = [
  {
    id: 1,
    nombre: 'Laptop Dell XPS 13',
    categoria: 'Tecnología',
    precio: 1200,
    stock: 15
  },
  {
    id: 2,
    nombre: 'Monitor LG 27" 4K',
    categoria: 'Tecnología',
    precio: 350,
    stock: 4
  },
  {
    id: 3,
    nombre: 'Silla Ergonómica Pro',
    categoria: 'Oficina',
    precio: 250,
    stock: 8
  }
];

let nextId = 4;

app.get('/productos', (req, res) => res.json(productos));

app.post('/productos', (req, res) => {
  const { nombre, categoria, precio, stock } = req.body;
  const nuevo = {
    id: nextId++,
    nombre,
    categoria,
    precio: Number(precio),
    stock: Number(stock)
  };

  productos.push(nuevo);
  res.status(201).json(nuevo);
});

app.put('/productos/:id', (req, res) => {
  const id = parseInt(req.params.id);

  const { nombre, categoria, precio, stock } = req.body;

  const index = productos.findIndex(p => p.id === id);

  if (index !== -1) {
    productos[index] = {
      ...productos[index],
      nombre,
      categoria,
      precio: Number(precio),
      stock: Number(stock)
    };

    return res.json(productos[index]);
  }

  res.status(404).json({ mensaje: 'No encontrado' });
});

app.delete('/productos/:id', (req, res) => {
  const id = parseInt(req.params.id);

  productos = productos.filter(p => p.id !== id);

  res.json({ mensaje: 'Eliminado', id });
});

app.listen(PORT, () => {
  console.log(`Backend corriendo en puerto ${PORT}`);
});

Paso 2: Creación del Dashboard Reactivo

El frontend desarrollado con React y Vite permite gestionar el inventario mediante una interfaz moderna y dinámica.

Código Principal del Frontend

import React, { useState, useEffect } from 'react';

const API_URL = 'http://localhost:5000/productos';

function App() {

  const [productos, setProductos] = useState([]);

  useEffect(() => {
    fetch(API_URL)
      .then(res => res.json())
      .then(datos => setProductos(datos));
  }, []);

  return (
    <div className="app-container">
      {/* Tabla, buscador, formularios y modales */}
    </div>
  );
}

export default App;

Demostración del Flujo CRUD

A) Operación de Inserción (Agregar Producto)

Al introducir los datos de un nuevo producto en el formulario interactivo:

Figura 2. Formulario de Alta de Producto

Formulario de Inserción de Productos

Una vez enviado el formulario, el nuevo producto se registra en el backend y aparece inmediatamente en la tabla sin necesidad de refrescar la página.

Figura 3. Producto Añadido al Inventario

Reactividad al Agregar Nuevo Producto

B) Operación de Edición (Actualizar Producto)

Al pulsar el botón de edición, los datos existentes se cargan automáticamente en el formulario.

Figura 4. Modo Edición Activado

Activación del Modo Edición de Productos

Tras guardar los cambios, la información actualizada se refleja automáticamente en la interfaz gracias al sistema reactivo de React.

Figura 5. Producto Actualizado

Reactividad en Tiempo Real al Actualizar

Paso 3: Diseño UI Moderno con CSS

Para minimizar dependencias externas, se utilizó CSS puro implementando efectos visuales modernos como Glassmorphism.

Estilo del Modal

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  background-color: rgba(15, 23, 42, 0.45);
  backdrop-filter: blur(8px);

  display: flex;
  justify-content: center;
  align-items: center;

  z-index: 2000;
}

Confirmación de Eliminación Personalizada

En lugar de utilizar la función nativa window.confirm(), se diseñó un modal personalizado para ofrecer una experiencia visual más profesional.

Tabla de Inventario con Acciones

Figura 6. Tabla Principal con Botones CRUD

Listado de Existencias y Acciones CRUD

Modal de Confirmación

Figura 7. Modal de Eliminación Personalizado

Modal de Confirmación Personalizado

Eliminación Exitosa

Tras confirmar la operación, el producto desaparece de la tabla sin recargar la página.

Figura 8. Inventario Actualizado Tras la Eliminación

Reactividad en Tiempo Real post-eliminación

🛡️ Mejores Prácticas y Lecciones Aprendidas

Middleware CORS

Debe inicializarse antes de definir las rutas para evitar bloqueos de seguridad en el navegador.

UX Profesional

Sustituir funciones nativas como window.confirm() por modales personalizados mejora significativamente la experiencia de usuario.

Persistencia de Datos

Aunque la persistencia en memoria resulta útil para prototipos, en producción se recomienda utilizar:

  • Prisma ORM
  • Sequelize ORM
  • PostgreSQL
  • MySQL

Estas tecnologías garantizan integridad, seguridad y persistencia real de los datos.


💬 Debate de Arquitectura

Gestión del Estado

useState

Adecuado para:

  • Aplicaciones pequeñas.
  • Inventarios básicos.
  • Proyectos académicos.
  • Equipos reducidos.

Context API o Redux

Recomendado para:

  • Aplicaciones empresariales.
  • Sistemas complejos.
  • Grandes volúmenes de datos.
  • Equipos de desarrollo amplios.

SEO y Rendimiento

SPA Pura

Ventajas

  • Gran velocidad de interacción.
  • Excelente experiencia de usuario.

Desventajas

  • SEO limitado.

SSR con Next.js

Ventajas

  • Mejor posicionamiento en buscadores.
  • Mayor rendimiento inicial.

Es la opción recomendada cuando el SEO constituye un requisito estratégico del negocio.


🎯 Conclusiones

La arquitectura SPA basada en React y Express proporciona una solución moderna, escalable y eficiente para aplicaciones empresariales como los sistemas de gestión de inventario.

La separación entre frontend y backend facilita:

  • Escalabilidad.
  • Mantenibilidad.
  • Reutilización de servicios.
  • Mejor experiencia de usuario.
  • Evolución futura hacia arquitecturas cloud y microservicios.

Este proyecto demuestra cómo una arquitectura desacoplada puede ofrecer un producto robusto, moderno y alineado con las prácticas profesionales actuales del desarrollo Full Stack.


👨‍💻 Información del Autor

AtributoDetalle
AutorDAVID MARTÍNEZ ESTÉBANEZ
FormaciónMáster en Desarrollo Full Stack y Arquitecturas Cloud
InstituciónTajamar Tech (2025-2026)
GitHubhttps://github.com/davidmartinezestebanez/inventario-spa
LinkedInhttps://www.linkedin.com/in/davidmartinezestebanez

ENLACE VIDEO: https://youtu.be/zV8VMOoYbxQ

Categorías: Desarrollo Web, React, Node.js, Full Stack, Arquitectura de Software

Etiquetas: React, Vite, Express, Node.js, API REST, SPA, Full Stack, JavaScript, Inventario, UX, Frontend, Backend.

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.