📝 Desarrollo-Web
← Volver

🌐 Guía Definitiva de Desarrollo Web Moderno y Backend

Nivel: Principiante → Intermedio → Avanzado
Objetivo: Entender qué es cada tecnología, cómo funciona por dentro y cómo se relacionan entre sí.
Formato: Chuleta avanzada — conceptual, técnica y comparativa.


📋 Índice

  1. Conceptos Previos Fundamentales
  2. HTML
  3. CSS
  4. JavaScript
  5. TypeScript
  6. DOM (Document Object Model)
  7. Virtual DOM
  8. JSON
  9. React
  10. Angular
  11. Vue.js
  12. Node.js
  13. Java y la JVM
  14. Spring Boot
  15. DOM vs Virtual DOM — Teoría Profunda
  16. Renderizado en Frameworks Modernos
  17. Comunicación Frontend ↔ Backend
  18. Tablas Comparativas

1. Conceptos Previos Fundamentales

Antes de estudiar cada tecnología en detalle, es importante entender el flujo general de cómo funciona la web:

Usuario (navegador)
     ↕  HTTP/HTTPS
Servidor (backend)
     ↕  Consultas
Base de datos

2. HTML

¿Qué es?

HTML (HyperText Markup Language) es el lenguaje de marcado estándar para crear la estructura de páginas web. Define qué hay en una página (texto, imágenes, formularios, enlaces), no cómo se ve ni cómo se comporta.

Tipo

Quién lo desarrolla

Nivel de tipado

Cómo funciona internamente

  1. El navegador descarga el archivo .html desde el servidor.
  2. El motor HTML del navegador (parser) lo lee de arriba a abajo, token a token.
  3. Construye el árbol DOM (ver sección DOM).
  4. Cuando encuentra <link> (CSS) o <script> (JS), puede pausar el parsing para cargarlos.
  5. Una vez completo el DOM, el navegador lo combina con los estilos (CSSOM) para generar el Render Tree y pintarlo en pantalla.

Para qué se usa

Características principales

Arquitectura / Modelo mental

HTML sigue una estructura jerárquica en árbol:

<html>
 ├── <head>  (metadatos, estilos, scripts)
 └── <body>  (contenido visible)
      ├── <header>
      ├── <main>
      │    ├── <section>
      │    └── <article>
      └── <footer>

Relación con el DOM

HTML es el origen del DOM. Cuando el navegador parsea el HTML, crea los nodos del árbol DOM. Modificar el HTML directamente no es lo mismo que modificar el DOM en tiempo de ejecución (JavaScript modifica el DOM, no el HTML fuente).

Ventajas

Desventajas

Ejemplo simple

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Mi página</title>
  </head>
  <body>
    <h1>Hola, mundo</h1>
    <p>Esta es mi primera página web.</p>
    <a href="https://ejemplo.com">Visitar</a>
  </body>
</html>

3. CSS

¿Qué es?

CSS (Cascading Style Sheets) es el lenguaje de estilos que describe cómo se presenta visualmente el contenido HTML: colores, tipografía, layout, animaciones, responsividad, etc.

Tipo

Quién lo desarrolla

W3C (World Wide Web Consortium), con implementación en motores de navegador: Blink (Chrome), Gecko (Firefox), WebKit (Safari).

Nivel de tipado

Cómo funciona internamente

  1. El navegador descarga y parsea los archivos .css.
  2. Construye el CSSOM (CSS Object Model), análogo al DOM pero para estilos.
  3. DOM + CSSOM = Render Tree (solo nodos visibles con sus estilos calculados).
  4. Layout (Reflow): calcula posiciones y tamaños.
  5. Paint: dibuja píxeles en pantalla.
  6. Compositing: combina capas (importante para animaciones con transform y opacity).

La "cascada" (cascade) determina qué regla gana cuando hay conflicto: importancia (!important) > especificidad (id > class > tag) > orden de aparición.

Para qué se usa

Características principales

Arquitectura / Modelo mental

Elemento HTML
     │
     ▼
Box Model:
┌─────────────────────────┐
│         margin          │
│  ┌───────────────────┐  │
│  │      border       │  │
│  │  ┌─────────────┐  │  │
│  │  │   padding   │  │  │
│  │  │  ┌───────┐  │  │  │
│  │  │  │content│  │  │  │
│  │  │  └───────┘  │  │  │
│  │  └─────────────┘  │  │
│  └───────────────────┘  │
└─────────────────────────┘

Relación con el DOM

CSS no modifica el DOM directamente, pero a través de JavaScript se puede manipular el atributo style de un nodo o añadir/quitar clases para cambiar estilos dinámicamente.

Ventajas

Desventajas

Ejemplo simple

/* Variables globales */
:root {
  --color-primario: #2563eb;
  --fuente-base: 16px;
}

/* Selector de clase */
.tarjeta {
  background-color: white;
  border-radius: 8px;
  padding: 1rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  max-width: 400px;
}

/* Pseudoclase */
.tarjeta:hover {
  transform: translateY(-2px);
  transition: transform 0.2s ease;
}

/* Media query */
@media (max-width: 600px) {
  .tarjeta {
    padding: 0.5rem;
  }
}

4. JavaScript

¿Qué es?

JavaScript (JS) es un lenguaje de programación interpretado, de alto nivel, orientado a objetos con prototipos y con soporte para programación funcional. Es el único lenguaje de programación nativo del navegador y es el motor de interactividad en la web.

Tipo

Quién lo desarrolla

Nivel de tipado

Cómo funciona internamente

Motor JavaScript (V8 como ejemplo)

  1. Parsing: el código fuente se convierte en un AST (Abstract Syntax Tree).
  2. Interpretación: el intérprete (Ignition en V8) genera bytecode.
  3. JIT Compilation: el compilador optimizador (TurboFan en V8) compila las partes "calientes" a código máquina nativo.
  4. Garbage Collection: gestión automática de memoria (Mark & Sweep).

Event Loop (fundamental)

JavaScript es single-threaded (un solo hilo de ejecución). El Event Loop permite la asincronía:

┌─────────────────────────┐
│      Call Stack         │  ← Ejecuta funciones síncronas
└────────────┬────────────┘
             │
┌────────────▼────────────┐
│    Web APIs / Node APIs │  ← setTimeout, fetch, fs, etc.
└────────────┬────────────┘
             │
┌────────────▼────────────┐
│      Callback Queue     │  ← Callbacks listos para ejecutar
│      (Task Queue)       │
└────────────┬────────────┘
             │
┌────────────▼────────────┐
│      Microtask Queue    │  ← Promises, queueMicrotask
└────────────┬────────────┘
             │
             ▼
        Event Loop
   (mueve tareas al Call Stack cuando está vacío)

Regla clave: las microtareas (Promises) tienen prioridad sobre las macrotareas (setTimeout).

Para qué se usa

Características principales

Arquitectura / Modelo mental

Relación con el DOM

JavaScript es el lenguaje que manipula el DOM en tiempo de ejecución:

// Seleccionar elemento
const titulo = document.querySelector('#titulo');

// Modificar contenido
titulo.textContent = 'Nuevo título';

// Escuchar eventos
document.querySelector('#btn').addEventListener('click', () => {
  console.log('Clic recibido');
});

Ventajas

Desventajas

Ejemplo simple

// Variables y tipos
const nombre = "Ana";
let edad = 28;

// Función flecha
const saludar = (persona) => `Hola, ${persona}!`;

// Promesas y async/await
async function obtenerUsuario(id) {
  try {
    const response = await fetch(`/api/usuarios/${id}`);
    const datos = await response.json();
    return datos;
  } catch (error) {
    console.error('Error:', error);
  }
}

// Destructuring
const { nombre: nombreUsuario, email } = await obtenerUsuario(1);

// Array methods funcionales
const numeros = [1, 2, 3, 4, 5];
const pares = numeros.filter(n => n % 2 === 0);     // [2, 4]
const dobles = numeros.map(n => n * 2);              // [2, 4, 6, 8, 10]
const suma = numeros.reduce((acc, n) => acc + n, 0); // 15

5. TypeScript

¿Qué es?

TypeScript (TS) es un superconjunto tipado de JavaScript desarrollado por Microsoft. Añade tipado estático opcional al lenguaje y compila a JavaScript puro. Cualquier código JavaScript válido es también TypeScript válido.

Tipo

Quién lo desarrolla

Microsoft (open source). Creado por Anders Hejlsberg (también creador de C#). Comunidad activa en GitHub.

Nivel de tipado

Cómo funciona internamente

  1. Escribes código .ts.
  2. El compilador TypeScript (tsc) verifica los tipos → si hay errores, los reporta.
  3. El compilador transpila el código a .js (elimina las anotaciones de tipo).
  4. El .js resultante corre en el navegador o Node.js normalmente.

TypeScript no existe en runtime: es puramente una herramienta de desarrollo. En producción, corre JavaScript.

código .ts → tsc (compilador) → código .js → motor JS (V8, etc.)
                    ↑
             Verifica tipos
             (solo en compilación)

Para qué se usa

Características principales

Arquitectura / Modelo mental

TypeScript agrega una capa de seguridad encima de JavaScript:

TypeScript
┌──────────────────────────────┐
│  Tipos + Interfaces          │
│  Generics + Enums            │
│  Decorators + Namespaces     │
└──────────────┬───────────────┘
               │ compila a
               ▼
          JavaScript

Relación con el DOM

TypeScript incluye definiciones de tipos para el DOM (lib.dom.d.ts). Esto significa que al trabajar con el DOM obtienes autocompletado y verificación de tipos:

const boton = document.querySelector<HTMLButtonElement>('#btn')!;
boton.addEventListener('click', (e: MouseEvent) => {
  console.log(e.target);
});

Ventajas

Desventajas

Ejemplo simple

// Interfaces
interface Usuario {
  id: number;
  nombre: string;
  email: string;
  rol: 'admin' | 'usuario' | 'moderador'; // Union type
  createdAt?: Date; // Opcional
}

// Generics
function obtenerPrimero<T>(array: T[]): T | undefined {
  return array[0];
}

// Clase tipada
class ServicioUsuarios {
  private usuarios: Usuario[] = [];

  agregarUsuario(usuario: Usuario): void {
    this.usuarios.push(usuario);
  }

  buscarPorId(id: number): Usuario | undefined {
    return this.usuarios.find(u => u.id === id);
  }

  obtenerPorRol(rol: Usuario['rol']): Usuario[] {
    return this.usuarios.filter(u => u.rol === rol);
  }
}

// Uso
const servicio = new ServicioUsuarios();
servicio.agregarUsuario({
  id: 1,
  nombre: 'Ana García',
  email: 'ana@ejemplo.com',
  rol: 'admin'
});

const primerNumero = obtenerPrimero([1, 2, 3]); // TypeScript infiere: number | undefined

6. DOM (Document Object Model)

¿Qué es?

El DOM es una representación en memoria del documento HTML/XML como un árbol de objetos que el navegador crea al cargar una página. JavaScript puede leer y modificar este árbol para cambiar dinámicamente el contenido, estructura y estilos de la página.

Tipo

Quién lo desarrolla

WHATWG y W3C, implementado por cada navegador.

Nivel de tipado

No aplica como lenguaje, pero el DOM expone una API con tipos bien definidos (HTMLElement, Node, Event, etc.).

Cómo funciona internamente

Cuando el navegador carga un HTML, el proceso es:

HTML (texto) 
     ↓ Parser
Tokens (tags, atributos)
     ↓
AST (árbol sintáctico)
     ↓
DOM Tree (objetos en memoria)

Cada elemento HTML se convierte en un Nodo del árbol:
- Document: raíz del árbol
- Element nodes: <div>, <p>, etc.
- Text nodes: el texto dentro de los elementos
- Attribute nodes: atributos de los elementos
- Comment nodes: comentarios HTML

Document
└── html (HTMLHtmlElement)
    ├── head (HTMLHeadElement)
    │   └── title → "Mi página" (Text)
    └── body (HTMLBodyElement)
        ├── h1 → "Hola" (Text)
        └── div.contenedor
            └── p → "Párrafo" (Text)

Para qué se usa

Características principales

Arquitectura / Modelo mental

JavaScript ←→ DOM API ←→ Árbol DOM ←→ Render Engine → Pantalla

Cuando JS modifica el DOM, el navegador puede necesitar recalcular:
- Reflow / Layout: si cambian dimensiones o posición.
- Repaint: si cambian colores o visibilidad (sin reflow).
- Composite: solo si se usan propiedades de compositing.

Reflow es costoso — involucra recalcular el layout de toda la página o parte de ella.

Ventajas

Desventajas

Ejemplo simple

// Selección
const lista = document.querySelector('#mi-lista');
const items = document.querySelectorAll('.item');

// Creación y adición
const nuevoItem = document.createElement('li');
nuevoItem.textContent = 'Nuevo elemento';
nuevoItem.classList.add('item', 'activo');
lista.appendChild(nuevoItem);

// Modificación
items.forEach(item => {
  item.style.color = 'navy';
});

// Eliminación
const itemObsoleto = document.querySelector('.obsoleto');
itemObsoleto.remove();

// Eventos (bubbling: sube del hijo al padre)
document.querySelector('#formulario').addEventListener('submit', (e) => {
  e.preventDefault(); // Previene recarga de página
  const valor = e.target.querySelector('input').value;
  console.log('Enviado:', valor);
});

7. Virtual DOM

¿Qué es?

El Virtual DOM (VDOM) es una representación en memoria del DOM real, expresada como objetos JavaScript simples. Es una técnica para optimizar actualizaciones del DOM real minimizando las operaciones costosas.

Tipo

Quién lo desarrolla

Cómo funciona internamente

Estado cambia (setState / reactive data)
         ↓
  Nuevo Virtual DOM  ←──── render()
         ↓
  Algoritmo DIFF (comparación con VDOM anterior)
         ↓
  Lista de cambios mínimos
         ↓
  Actualización selectiva del DOM real

El Virtual DOM es simplemente un objeto JS:

// Esto es un nodo de Virtual DOM (simplificado)
{
  type: 'div',
  props: { className: 'contenedor', id: 'app' },
  children: [
    { type: 'h1', props: {}, children: ['Hola'] },
    { type: 'p', props: { className: 'texto' }, children: ['Párrafo'] }
  ]
}

Para qué se usa

Ventajas vs DOM real

Aspecto DOM Real Virtual DOM
Velocidad de operación Lento (reflow/repaint) Rápido (solo objetos JS)
Actualizaciones Cada cambio se refleja Se acumulan y se aplican juntos
API Verbose Abstracto (JSX, templates)
Control Manual Automático (el framework decide)

Relación con el DOM

El Virtual DOM es un intermediario entre el código del desarrollador y el DOM real. El framework se encarga de sincronizarlos eficientemente.


8. JSON

¿Qué es?

JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos, fácil de leer y escribir para humanos y de parsear para máquinas. Es el formato estándar de facto para APIs REST.

Tipo

Quién lo desarrolla

Propuesto por Douglas Crockford (~2001). Estandarizado por ECMA e IETF.

Nivel de tipado

JSON soporta tipos básicos:
- string, number, boolean, null
- array ([]), object ({})
- No soporta: funciones, undefined, fechas nativas, NaN, Infinity.

Cómo funciona internamente

JSON es texto plano con estructura. No es código ejecutable. Para usarlo en JS:

// Texto JSON → objeto JS
const objeto = JSON.parse('{"nombre": "Ana", "edad": 28}');

// Objeto JS → texto JSON
const texto = JSON.stringify({ nombre: "Ana", edad: 28 });
// '{"nombre":"Ana","edad":28}'

Para qué se usa

Características principales

Ejemplo

{
  "usuario": {
    "id": 42,
    "nombre": "Ana García",
    "email": "ana@ejemplo.com",
    "activo": true,
    "roles": ["admin", "editor"],
    "direccion": null,
    "configuracion": {
      "tema": "oscuro",
      "idioma": "es"
    }
  }
}

9. React

¿Qué es?

React es una librería JavaScript para construir interfaces de usuario basadas en componentes reutilizables. Gestiona el renderizado eficiente de la UI mediante el Virtual DOM. Es la más popular del ecosistema frontend actual.

⚠️ React es una librería (no un framework). Solo se ocupa de la vista (la "V" de MVC). Para routing, estado global, etc., necesitas librerías adicionales (React Router, Redux, Zustand...).

Tipo

Quién lo desarrolla

Meta (Facebook). Código abierto desde 2013. Comunidad masiva.

Nivel de tipado

Cómo funciona internamente

JSX

React introduce JSX, una extensión de sintaxis que permite escribir HTML dentro de JS:

// JSX (no es HTML real)
const elemento = <h1 className="titulo">Hola, {nombre}</h1>;

// Se compila a:
const elemento = React.createElement('h1', { className: 'titulo' }, `Hola, ${nombre}`);

Ciclo de vida de un componente

Montaje → Actualización → Desmontaje
  ↓            ↓              ↓
render()   setState()     cleanup
useEffect  re-render     useEffect return

Hooks (React 16.8+)

Los hooks reemplazaron las clases para gestionar estado y efectos en componentes funcionales:
- useState: estado local del componente.
- useEffect: efectos secundarios (fetch, suscripciones, DOM).
- useContext: acceso al contexto global.
- useRef: referencias a elementos DOM.
- useMemo, useCallback: optimización de rendimiento.
- useReducer: estado complejo tipo Redux.

Flujo de datos

React sigue un flujo unidireccional (one-way data flow):

Estado (state) → Render → UI
      ↑                    ↓
      └──── eventos ◄──────┘

Para qué se usa

Características principales

Arquitectura / Modelo mental

App (componente raíz)
├── Header
│   ├── Logo
│   └── Nav
│       ├── NavItem
│       └── NavItem
├── Main
│   ├── Sidebar
│   └── Content
│       └── ArticleCard (x N)
└── Footer

Cada componente gestiona su propio estado. Los datos bajan por props, los eventos suben por callbacks.

Relación con el DOM

React no manipula el DOM directamente en el código del desarrollador. Usa el Virtual DOM como intermediario. El algoritmo Fiber Reconciler decide qué nodos del DOM real actualizar.

Ventajas

Desventajas

Ejemplo simple

import { useState, useEffect } from 'react';

// Componente hijo
function TarjetaUsuario({ nombre, email, onEliminar }) {
  return (
    <div className="tarjeta">
      <h3>{nombre}</h3>
      <p>{email}</p>
      <button onClick={onEliminar}>Eliminar</button>
    </div>
  );
}

// Componente padre
function ListaUsuarios() {
  const [usuarios, setUsuarios] = useState([]);
  const [cargando, setCargando] = useState(true);

  // Efecto: carga datos al montar el componente
  useEffect(() => {
    fetch('/api/usuarios')
      .then(res => res.json())
      .then(datos => {
        setUsuarios(datos);
        setCargando(false);
      });
  }, []); // [] = solo ejecutar una vez (al montar)

  const eliminar = (id) => {
    setUsuarios(prev => prev.filter(u => u.id !== id));
  };

  if (cargando) return <p>Cargando...</p>;

  return (
    <div>
      <h2>Usuarios ({usuarios.length})</h2>
      {usuarios.map(u => (
        <TarjetaUsuario
          key={u.id}
          nombre={u.nombre}
          email={u.email}
          onEliminar={() => eliminar(u.id)}
        />
      ))}
    </div>
  );
}

export default ListaUsuarios;

10. Angular

¿Qué es?

Angular es un framework completo para construir aplicaciones web (principalmente SPAs) desarrollado por Google. A diferencia de React, Angular es "opinionated" (tiene opiniones sobre cómo hacer las cosas) e incluye todo: routing, formularios, HTTP, animaciones, gestión de estado, etc.

⚠️ Angular ≠ AngularJS: AngularJS (v1) es el framework original de 2010. Angular (v2+, desde 2016) es una reescritura completa en TypeScript. Son tecnologías distintas.

Tipo

Quién lo desarrolla

Google, con amplia comunidad open source.

Nivel de tipado

Cómo funciona internamente

Compilación

Angular tiene dos modos:
- JIT (Just-In-Time): compila en el navegador (desarrollo).
- AOT (Ahead-Of-Time): compila en build time (producción). Genera código optimizado, elimina el compilador del bundle.

Change Detection

Angular no usa Virtual DOM. Usa un mecanismo llamado Change Detection:
1. Cada componente tiene una Change Detection Tree.
2. Cuando ocurre un evento (click, HTTP response, timer), Angular recorre el árbol de arriba abajo.
3. Compara los valores actuales con los anteriores.
4. Si hay cambios, actualiza el DOM real.

Zone.js: Angular usa Zone.js para "parchear" las APIs del navegador (setTimeout, addEventListener, fetch) y detectar cuándo puede haber habido cambios de estado. Así sabe cuándo ejecutar el ciclo de Change Detection.

OnPush strategy: optimización donde Angular solo chequea un componente si sus inputs cambiaron o si recibió un evento. Mejora rendimiento significativamente.

Módulos y componentes

AppModule (raíz)
├── Declarations: [AppComponent, NavComponent, ...]
├── Imports: [BrowserModule, RouterModule, HttpClientModule]
├── Providers: [ServicioUsuarios, AuthGuard]
└── Bootstrap: [AppComponent]

Dependency Injection (DI)

Angular tiene un sistema de Inyección de Dependencias muy robusto:

@Injectable({ providedIn: 'root' })
class ServicioUsuarios {
  constructor(private http: HttpClient) {}

  getUsuarios(): Observable<Usuario[]> {
    return this.http.get<Usuario[]>('/api/usuarios');
  }
}

@Component({...})
class ListaComponent {
  // Angular inyecta ServicioUsuarios automáticamente
  constructor(private usuarioService: ServicioUsuarios) {}
}

RxJS / Observables

Angular usa RxJS (programación reactiva) extensivamente:
- Observable: flujo de datos asíncrono.
- Subject, BehaviorSubject: para estado compartido.
- Operadores: map, filter, switchMap, combineLatest.

Para qué se usa

Características principales

Arquitectura / Modelo mental

Módulos (NgModules)
└── Componentes (View + Logic)
    ├── Template (HTML extendido)
    ├── Class (TypeScript)
    └── Styles (CSS/SCSS)
        └── usa Servicios (lógica de negocio)
            └── usa Repositorios/HttpClient (datos)

Relación con el DOM

Angular usa Change Detection (con Zone.js) en lugar de Virtual DOM. Accede al DOM real pero de forma controlada. También tiene Renderer2 para manipulación de DOM de forma agnóstica a la plataforma (útil para SSR o Web Workers).

Ventajas

Desventajas

Ejemplo simple

// usuario.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

interface Usuario {
  id: number;
  nombre: string;
  email: string;
}

@Injectable({ providedIn: 'root' })
export class UsuarioService {
  private apiUrl = '/api/usuarios';

  constructor(private http: HttpClient) {}

  getUsuarios(): Observable<Usuario[]> {
    return this.http.get<Usuario[]>(this.apiUrl);
  }

  eliminarUsuario(id: number): Observable<void> {
    return this.http.delete<void>(`${this.apiUrl}/${id}`);
  }
}

// lista.component.ts
import { Component, OnInit } from '@angular/core';
import { UsuarioService } from './usuario.service';

@Component({
  selector: 'app-lista',
  template: `
    <div *ngIf="cargando">Cargando...</div>
    <ul>
      <li *ngFor="let usuario of usuarios">
        {{ usuario.nombre }} - {{ usuario.email }}
        <button (click)="eliminar(usuario.id)">Eliminar</button>
      </li>
    </ul>
  `
})
export class ListaComponent implements OnInit {
  usuarios: Usuario[] = [];
  cargando = true;

  constructor(private usuarioService: UsuarioService) {}

  ngOnInit(): void {
    this.usuarioService.getUsuarios().subscribe({
      next: (datos) => {
        this.usuarios = datos;
        this.cargando = false;
      },
      error: (err) => console.error(err)
    });
  }

  eliminar(id: number): void {
    this.usuarioService.eliminarUsuario(id).subscribe(() => {
      this.usuarios = this.usuarios.filter(u => u.id !== id);
    });
  }
}

11. Vue.js

¿Qué es?

Vue.js es un framework progresivo para construir interfaces de usuario. "Progresivo" significa que puedes usarlo desde para añadir interactividad a una parte de una página existente hasta para construir SPAs complejas. Es considerado el más fácil de aprender de los tres grandes.

Tipo

Quién lo desarrolla

Evan You (ex-Google). Mantenido por la comunidad y sponsors. Vue 3 lanzado en 2020.

Nivel de tipado

Cómo funciona internamente

Reactividad

Vue 3 usa Proxy de JavaScript para implementar reactividad:

// Internamente, Vue hace algo así:
const estado = new Proxy({ contador: 0 }, {
  set(target, key, value) {
    target[key] = value;
    // Notifica a todos los efectos que dependen de esta propiedad
    trigger(target, key);
    return true;
  },
  get(target, key) {
    // Rastrea qué efectos leen esta propiedad
    track(target, key);
    return target[key];
  }
});

Cuando un valor reactivo cambia, Vue sabe exactamente qué componentes dependen de él y los re-renderiza.

Virtual DOM en Vue

Vue también usa Virtual DOM (llamado VNode). El proceso es similar a React: estado cambia → nuevo VDOM → diff → patch del DOM real. En Vue 3, el compilador optimiza agresivamente el VDOM (static hoisting, patch flags) para evitar diffs innecesarios.

Options API vs Composition API

Options API (Vue 2 style, también disponible en Vue 3):

export default {
  data() { return { contador: 0 } },
  computed: { doble() { return this.contador * 2 } },
  methods: { incrementar() { this.contador++ } },
  mounted() { console.log('Componente montado') }
}

Composition API (Vue 3, recomendado):

import { ref, computed, onMounted } from 'vue'

// Lógica agrupada por funcionalidad, no por tipo de opción
const contador = ref(0)
const doble = computed(() => contador.value * 2)
const incrementar = () => contador.value++
onMounted(() => console.log('Montado'))

Para qué se usa

Características principales

Arquitectura / Modelo mental

<template>  →  Virtual DOM  →  DOM Real
    ↑                ↑
<script>    →  Reactive System
(ref, computed)
    ↑
<style scoped>

Single File Component:

<template>
  <!-- HTML con directivas Vue -->
</template>

<script setup>
  // Lógica del componente (Composition API)
</script>

<style scoped>
  /* CSS con scope automático al componente */
</style>

Relación con el DOM

Vue usa Virtual DOM (VNodes) + sistema reactivo basado en Proxy. Cuando los datos reactivos cambian, Vue recalcula el VDOM, hace diff con el anterior y aplica los cambios mínimos al DOM real.

Ventajas

Desventajas

Ejemplo simple

<template>
  <div>
    <h2>Usuarios ({{ usuarios.length }})</h2>
    <p v-if="cargando">Cargando...</p>
    <ul v-else>
      <li v-for="usuario in usuarios" :key="usuario.id">
        {{ usuario.nombre }}{{ usuario.email }}
        <button @click="eliminar(usuario.id)"></button>
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const usuarios = ref([])
const cargando = ref(true)

onMounted(async () => {
  const res = await fetch('/api/usuarios')
  usuarios.value = await res.json()
  cargando.value = false
})

function eliminar(id) {
  usuarios.value = usuarios.value.filter(u => u.id !== id)
}
</script>

<style scoped>
li {
  padding: 0.5rem;
  border-bottom: 1px solid #eee;
}
</style>

12. Node.js

¿Qué es?

Node.js es un entorno de ejecución (runtime) de JavaScript construido sobre el motor V8 de Chrome. Permite ejecutar JavaScript fuera del navegador, principalmente en el servidor. No es un framework, ni un lenguaje: es el entorno que hace posible ejecutar JS en el backend.

Tipo

Quién lo desarrolla

Creado por Ryan Dahl (2009). Mantenido por la OpenJS Foundation y la comunidad.

Nivel de tipado

Cómo funciona internamente

Arquitectura

JavaScript Code
      ↓
   V8 Engine  (ejecuta JS, JIT compilation)
      ↓
  Node.js APIs (fs, http, crypto, path...)
      ↓
  libuv  (I/O asíncrono, Thread Pool, Event Loop)
      ↓
Sistema Operativo (filesystem, red, etc.)

libuv y el Event Loop

libuv es la librería C que implementa el Event Loop de Node.js. Permite I/O no bloqueante:

Event Loop (single thread):
 ┌──────────────────────┐
 │  timers              │  → setTimeout, setInterval
 │  pending callbacks   │  → errores de I/O del ciclo anterior
 │  idle, prepare       │  → interno
 │  poll                │  → nuevos eventos I/O (la fase principal)
 │  check               │  → setImmediate
 │  close callbacks     │  → socket.on('close')
 └──────────────────────┘
        ↑______________|

Thread Pool (libuv): para operaciones que no pueden ser asíncronas nativamente (crypto, fs en ciertos casos, DNS), Node usa un pool de hilos (4 por defecto).

Modelo I/O no bloqueante: Node puede manejar miles de conexiones concurrentes sin bloquear porque no espera a que termine el I/O — delega a libuv y sigue procesando otros eventos.

// BLOQUEANTE (mala práctica en Node)
const datos = fs.readFileSync('/archivo.txt'); // DETIENE el Event Loop
procesar(datos);

// NO BLOQUEANTE (correcto)
fs.readFile('/archivo.txt', (err, datos) => {
  procesar(datos);
});
// Node continúa ejecutando mientras espera el archivo

Para qué se usa

Características principales

Arquitectura / Modelo mental

Request 1 → Node.js (single thread)
Request 2 →    ↓
Request 3 →  Event Loop ←→ I/O async (libuv)
               ↓
           Response 1, 2, 3... (cuando I/O completa)

Node es excelente para cargas I/O-bound (muchas solicitudes, poco cómputo). Es peor para tareas CPU-bound intensas (procesamiento de imágenes, cálculos matemáticos) porque bloquea el Event Loop.

Relación con el DOM

Ninguna. Node.js no tiene DOM — es un entorno de servidor. No hay navegador ni ventana. Sin embargo, herramientas como jsdom o happy-dom simulan el DOM en Node para testing.

Ventajas

Desventajas

Ejemplo simple (servidor HTTP con Express)

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

app.use(express.json()); // middleware para parsear JSON

// Datos en memoria (simplificado)
let usuarios = [
  { id: 1, nombre: 'Ana', email: 'ana@ejemplo.com' },
  { id: 2, nombre: 'Luis', email: 'luis@ejemplo.com' }
];

// GET /api/usuarios
app.get('/api/usuarios', (req, res) => {
  res.json(usuarios);
});

// GET /api/usuarios/:id
app.get('/api/usuarios/:id', (req, res) => {
  const usuario = usuarios.find(u => u.id === Number(req.params.id));
  if (!usuario) return res.status(404).json({ error: 'No encontrado' });
  res.json(usuario);
});

// POST /api/usuarios
app.post('/api/usuarios', (req, res) => {
  const { nombre, email } = req.body;
  const nuevo = { id: Date.now(), nombre, email };
  usuarios.push(nuevo);
  res.status(201).json(nuevo);
});

// DELETE /api/usuarios/:id
app.delete('/api/usuarios/:id', (req, res) => {
  const id = Number(req.params.id);
  usuarios = usuarios.filter(u => u.id !== id);
  res.status(204).send();
});

app.listen(3000, () => console.log('Servidor en http://localhost:3000'));

13. Java y la JVM

¿Qué es Java?

Java es un lenguaje de programación orientado a objetos, fuertemente tipado, compilado y multiplataforma. Diseñado bajo el principio "Write Once, Run Anywhere" (WORA): el código Java compilado puede ejecutarse en cualquier sistema que tenga una JVM instalada.

Tipo

Quién lo desarrolla

Creado por James Gosling en Sun Microsystems (1995). Actualmente desarrollado y mantenido por Oracle (open source bajo OpenJDK).

Nivel de tipado

Cómo funciona internamente — La JVM

Código Java (.java)
       ↓  javac (compilador)
   Bytecode (.class)
       ↓  JVM (Java Virtual Machine)
  Interpretación + JIT
       ↓
Código máquina nativo
       ↓
  Sistema Operativo

¿Qué es la JVM?

La Java Virtual Machine es una máquina virtual que:
1. Carga el bytecode (.class).
2. Verifica que sea seguro.
3. Interpreta el bytecode o lo compila JIT a código máquina nativo.
4. Gestiona memoria automáticamente (Garbage Collector).

La JVM abstrae el sistema operativo: el mismo .class corre en Windows, Linux o macOS sin cambios.

JVM Memory Model

JVM Memory:
┌────────────────────────────────────────┐
│  Method Area (Metaspace en Java 8+)    │  ← Clases, métodos, constantes
│  Heap                                  │  ← Objetos (gestionado por GC)
│    ├── Young Generation                │    ← Objetos nuevos
│    │     ├── Eden Space                │
│    │     └── Survivor Spaces (S0, S1)  │
│    └── Old Generation (Tenured)        │    ← Objetos longevos
├────────────────────────────────────────┤
│  Stack (por hilo)                      │  ← Frames de métodos, variables locales
│  PC Register (por hilo)                │  ← Instrucción actual
│  Native Method Stack                   │  ← Métodos nativos (C/C++)
└────────────────────────────────────────┘

Garbage Collector

Java gestiona la memoria automáticamente. El GC libera objetos no referenciados. Existen varios algoritmos (G1GC, ZGC, Shenandoah) con diferentes trade-offs entre throughput y latencia.

Para qué se usa Java

Características principales

Arquitectura / Modelo mental

Aplicación Java
├── Paquetes (packages = namespaces)
│   └── Clases
│       ├── Atributos (estado)
│       ├── Constructores
│       └── Métodos (comportamiento)
│           └── usa otros objetos
└── Main (punto de entrada)

Relación con el DOM

Ninguna en el sentido clásico. Java es lenguaje de servidor. Puede generar HTML (en tecnologías legacy como JSP/Thymeleaf), pero no manipula el DOM del navegador directamente.

Ejemplo simple

import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

// Clase de datos (Record en Java 14+)
public record Usuario(int id, String nombre, String email) {}

public class ServicioUsuarios {
    private List<Usuario> usuarios = new ArrayList<>();

    public void agregar(Usuario u) {
        usuarios.add(u);
    }

    public List<Usuario> buscarPorNombre(String nombre) {
        return usuarios.stream()
            .filter(u -> u.nombre().toLowerCase().contains(nombre.toLowerCase()))
            .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        ServicioUsuarios servicio = new ServicioUsuarios();
        servicio.agregar(new Usuario(1, "Ana García", "ana@ejemplo.com"));
        servicio.agregar(new Usuario(2, "Luis Pérez", "luis@ejemplo.com"));

        List<Usuario> encontrados = servicio.buscarPorNombre("ana");
        encontrados.forEach(u -> System.out.println(u.nombre()));
        // Output: Ana García
    }
}

14. Spring Boot

¿Qué es?

Spring Boot es un framework de Java basado en el ecosistema Spring que simplifica enormemente la creación de aplicaciones Java empresariales. Su filosofía es "Convention over Configuration": provee configuraciones sensatas por defecto para que puedas arrancar rápidamente sin configurar nada manualmente.

Spring Boot no reemplaza a Spring — es Spring con autoconfiguración.

Tipo

Quién lo desarrolla

VMware (Pivotal), con comunidad activa. Parte del ecosistema Spring (Spring Framework, Spring Data, Spring Security, Spring Cloud...).

Nivel de tipado

Estático — hereda el tipado fuerte de Java.

Cómo funciona internamente

Autoconfiguración

Spring Boot escanea el classpath, detecta las dependencias presentes y configura automáticamente beans y componentes:

Tienes spring-boot-starter-web en tu pom.xml?
  → Spring Boot configura automáticamente:
     - Tomcat (servidor embebido)
     - DispatcherServlet (controlador frontal MVC)
     - Jackson (serialización JSON)
     - etc.

Inyección de Dependencias (DI) y el Contenedor IoC

IoC (Inversion of Control): en lugar de que tu código cree sus dependencias (new ServicioUsuarios()), le dices a Spring qué clases necesitas y él las crea, gestiona y conecta.

// Sin IoC (acoplamiento fuerte)
public class ControladorUsuarios {
    private ServicioUsuarios servicio = new ServicioUsuarios(); // ← MALO
}

// Con IoC / DI
@RestController
public class ControladorUsuarios {
    private final ServicioUsuarios servicio;

    // Spring inyecta la dependencia automáticamente
    public ControladorUsuarios(ServicioUsuarios servicio) {
        this.servicio = servicio;
    }
}

El Contenedor IoC de Spring es el responsable de:
1. Escanear las clases anotadas.
2. Crear instancias (beans) y gestionar su ciclo de vida.
3. Resolver y conectar las dependencias.

Arquitectura MVC en Spring Boot

HTTP Request
     ↓
DispatcherServlet (Front Controller)
     ↓
@RestController (Capa de Presentación)
     ↓ llama a
@Service (Capa de Negocio)
     ↓ llama a
@Repository (Capa de Persistencia)
     ↓
Base de Datos
     ↓ (retorno)
     ↑ responde con objeto Java
     ↑ Jackson lo convierte a JSON
HTTP Response (JSON)

Las 3 capas clave

1. Controller (@RestController / @Controller)
- Recibe las peticiones HTTP.
- Valida la entrada básica.
- Delega al Service.
- Retorna la respuesta (JSON para REST).

2. Service (@Service)
- Contiene la lógica de negocio.
- Orquesta las operaciones.
- Aplica reglas del dominio.
- Transacciones (@Transactional).

3. Repository (@Repository)
- Acceso a datos (base de datos).
- Abstracción sobre JDBC / JPA / Hibernate.
- Con Spring Data JPA: solo defines la interfaz, Spring genera la implementación.

Para qué se usa

Características principales

Ejemplo completo: API REST con Spring Boot

// Entidad JPA (mapea a tabla de BD)
@Entity
@Table(name = "usuarios")
public class Usuario {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String nombre;

    @Column(unique = true, nullable = false)
    private String email;

    // getters y setters...
}

// Repository (Spring Data genera la implementación)
@Repository
public interface UsuarioRepository extends JpaRepository<Usuario, Long> {
    // Spring genera: findAll(), findById(), save(), deleteById()...

    // Método personalizado (Spring genera la query automáticamente)
    List<Usuario> findByNombreContainingIgnoreCase(String nombre);

    Optional<Usuario> findByEmail(String email);
}

// Service (lógica de negocio)
@Service
public class UsuarioService {
    private final UsuarioRepository repositorio;

    public UsuarioService(UsuarioRepository repositorio) {
        this.repositorio = repositorio;
    }

    public List<Usuario> obtenerTodos() {
        return repositorio.findAll();
    }

    public Usuario obtenerPorId(Long id) {
        return repositorio.findById(id)
            .orElseThrow(() -> new RuntimeException("Usuario no encontrado"));
    }

    @Transactional
    public Usuario crear(Usuario usuario) {
        if (repositorio.findByEmail(usuario.getEmail()).isPresent()) {
            throw new IllegalArgumentException("Email ya registrado");
        }
        return repositorio.save(usuario);
    }

    @Transactional
    public void eliminar(Long id) {
        repositorio.deleteById(id);
    }
}

// Controller (API REST)
@RestController
@RequestMapping("/api/usuarios")
public class UsuarioController {
    private final UsuarioService servicio;

    public UsuarioController(UsuarioService servicio) {
        this.servicio = servicio;
    }

    @GetMapping
    public ResponseEntity<List<Usuario>> obtenerTodos() {
        return ResponseEntity.ok(servicio.obtenerTodos());
    }

    @GetMapping("/{id}")
    public ResponseEntity<Usuario> obtenerPorId(@PathVariable Long id) {
        return ResponseEntity.ok(servicio.obtenerPorId(id));
    }

    @PostMapping
    public ResponseEntity<Usuario> crear(@RequestBody @Valid Usuario usuario) {
        Usuario creado = servicio.crear(usuario);
        return ResponseEntity.status(HttpStatus.CREATED).body(creado);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> eliminar(@PathVariable Long id) {
        servicio.eliminar(id);
        return ResponseEntity.noContent().build();
    }
}

// Punto de entrada de la aplicación
@SpringBootApplication
public class AplicacionMain {
    public static void main(String[] args) {
        SpringApplication.run(AplicacionMain.class, args);
    }
}

Ventajas de Spring Boot

Desventajas


15. DOM vs Virtual DOM — Teoría Profunda

El problema del DOM real

El DOM real tiene dos problemas de rendimiento fundamentales:

1. Operaciones DOM son lentas
Aunque los motores de navegador han mejorado mucho, cada modificación al DOM puede desencadenar:
- Reflow (Layout): recalcular posiciones y tamaños de elementos.
- Repaint: redibujar los píxeles afectados.

El reflow es especialmente costoso porque puede invalidar el layout de toda la página.

2. Actualizaciones sin batching
Si tienes código que actualiza el DOM 100 veces en un loop:

// Malo: 100 reflows
for (let i = 0; i < 100; i++) {
  document.querySelector(`#item-${i}`).style.height = `${i * 10}px`;
}

Cada cambio puede forzar un reflow independiente.

Solución: Virtual DOM

El Virtual DOM resuelve esto creando una representación en memoria (un objeto JavaScript simple) del árbol del DOM real. Las operaciones en objetos JS son muchísimo más rápidas que en el DOM real.

El proceso completo con Virtual DOM (React como ejemplo)

Estado inicial: { items: ['A', 'B', 'C'] }
    ↓
Render → VDOM₁:
  <ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
  </ul>
    ↓ Se aplica al DOM real

Estado cambia: { items: ['A', 'X', 'C'] }
    ↓
Render → VDOM₂:
  <ul>
    <li>A</li>
    <li>X</li>  ← CAMBIÓ
    <li>C</li>
  </ul>
    ↓
DIFF (VDOM₁ vs VDOM₂):
  → Solo <li> en posición 1 cambió

PATCH:
  → DOM real: solo actualiza textContent del segundo <li>

En lugar de reemplazar todo el DOM, solo se aplica el mínimo cambio necesario.

Algoritmo de Diffing

El diff naïve de dos árboles tiene complejidad O(n³). React usa heurísticas para reducirlo a O(n):

  1. Misma posición, mismo tipo: compara atributos y desciende recursivamente.
  2. Misma posición, distinto tipo: destruye el nodo antiguo y crea uno nuevo.
  3. Listas con key: usa las keys para identificar elementos aunque cambien de posición.

Por eso la key en React y Vue es crítica:

// Sin key: React no puede identificar elementos en listas → reordena mal
{items.map(item => <li>{item.nombre}</li>)}

// Con key: React identifica cada elemento → actualizaciones eficientes
{items.map(item => <li key={item.id}>{item.nombre}</li>)}

Cómo Angular lo resuelve: Change Detection

Angular no usa Virtual DOM. En su lugar usa Change Detection:

Evento ocurre (click, HTTP, timer)
           ↓ Zone.js notifica a Angular
Angular ejecuta Change Detection:
  Recorre el árbol de componentes (top → down)
    Por cada componente:
      Compara valores actuales vs anteriores
      Si hay cambios → actualiza el DOM real

OnPush strategy: un componente Angular con ChangeDetectionStrategy.OnPush solo se chequea si:
- Sus @Input() props cambiaron (referencia diferente).
- Un evento originó en ese componente.
- Se marcó manualmente con markForCheck().
- Recibió un nuevo valor de un Observable al que está suscrito.

Comparación final

Aspecto DOM Real (vanilla) Virtual DOM (React/Vue) Change Detection (Angular)
Estrategia Manipulación directa Diff + patch Comparación de valores
Velocidad de actualización Depende del dev Automática + eficiente Eficiente con OnPush
Complejidad de uso Manual y verbose Declarativo Declarativo + observable
Overhead extra Ninguno Crear/comparar VDOM Zone.js + árbol de detección
Ideal para Scripts simples Apps complejas con mucho estado Apps empresariales grandes

16. Renderizado en Frameworks Modernos

Renderizado Inicial

Cuando una aplicación SPA carga por primera vez:

1. Navegador descarga index.html (casi vacío: solo <div id="root">)
2. Navegador descarga el bundle JS (React/Angular/Vue)
3. El framework ejecuta el código de inicialización
4. Renderiza toda la UI en el DOM (primera pintura)

En SSR (Server-Side Rendering, Next.js/Nuxt):

1. Servidor ejecuta el framework y genera HTML completo
2. Navegador recibe HTML con contenido ya visible
3. Framework "hidrata" la página (añade interactividad)

SSR mejora el tiempo de First Contentful Paint (FCP) y el SEO.

Re-renderizado

Cuando el estado cambia, el framework decide qué re-renderizar:

React:
- setState o cambio en hooks → componente + sus hijos se re-renderizan.
- React.memo, useMemo, useCallback → previenen re-renders innecesarios.
- Concurrent Mode: puede interrumpir renders para priorizar interacciones.

Vue:
- Sistema de reactividad con Proxy: solo los componentes que dependen del dato que cambió se re-renderizan.
- Más granular que React por defecto.

Angular:
- Change Detection recorre el árbol.
- Con OnPush: solo chequea componentes marcados.
- Con Signals (Angular 16+): granularidad similar a Vue.

Diffing (diferenciación)

El algoritmo de diff compara el árbol VDOM anterior con el nuevo:

VDOM anterior:            VDOM nuevo:
<div>                     <div>
  <h1>Título</h1>   →       <h1>Nuevo título</h1>  ← CAMBIÓ
  <p>Texto</p>              <p>Texto</p>            ← igual
  <ul>                      <ul>
    <li key="1">A</li>        <li key="1">A</li>    ← igual
    <li key="2">B</li>        <li key="3">C</li>    ← key cambió
  </ul>                     </ul>
</div>                    </div>

Resultado del diff:
- Actualizar textContent de h1
- Reusar <p> sin cambios
- Eliminar <li key="2">, crear <li key="3">

Reconciliación

La reconciliación es el proceso de aplicar el diff al DOM real:

  1. Crear: nodos nuevos → document.createElement + appendChild.
  2. Actualizar: atributos/texto cambiados → setAttribute, textContent.
  3. Mover: con keys, mover nodos existentes en lugar de recrearlos.
  4. Eliminar: nodos desaparecidos → removeChild.

React Fiber permite que la reconciliación sea interruptible: puede pausar, reanudar o abandonar trabajo de render para priorizar animaciones o interacciones del usuario.


17. Comunicación Frontend ↔ Backend

HTTP y el modelo Request/Response

Frontend (navegador)                    Backend (servidor)
        │                                      │
        │── GET /api/usuarios ────────────────►│
        │                                      │ consulta BD
        │◄─── 200 OK (JSON) ──────────────────│
        │                                      │
        │── POST /api/usuarios (body: JSON) ──►│
        │                                      │ inserta en BD
        │◄─── 201 Created (JSON) ─────────────│

REST (Representational State Transfer)

REST es un estilo arquitectónico para APIs web. Sus principios:
- Stateless: cada petición contiene toda la información necesaria.
- Recursos: los endpoints representan recursos (/usuarios, /productos).
- Verbos HTTP: definen la operación.
- Representación: los recursos se transmiten en JSON (o XML).

Verbo HTTP Operación CRUD Ejemplo
GET Read GET /api/usuarios → Lista todos
GET Read GET /api/usuarios/42 → Obtiene el #42
POST Create POST /api/usuarios (body: datos) → Crea nuevo
PUT Update (completo) PUT /api/usuarios/42 → Reemplaza #42
PATCH Update (parcial) PATCH /api/usuarios/42 → Actualiza campos
DELETE Delete DELETE /api/usuarios/42 → Elimina #42

Códigos de estado HTTP clave

Código Significado
200 OK Éxito
201 Created Recurso creado
204 No Content Éxito sin cuerpo (ej: DELETE)
400 Bad Request Error del cliente (datos inválidos)
401 Unauthorized No autenticado
403 Forbidden Autenticado pero sin permiso
404 Not Found Recurso no existe
422 Unprocessable Validación fallida
500 Internal Server Error Error del servidor

fetch API (frontend → backend)

// GET
const response = await fetch('/api/usuarios');
const usuarios = await response.json();

// POST con body JSON
const nuevoUsuario = await fetch('/api/usuarios', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ nombre: 'Ana', email: 'ana@ejemplo.com' })
}).then(res => res.json());

// Con manejo de errores
try {
  const res = await fetch('/api/usuarios/99');
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const usuario = await res.json();
} catch (err) {
  console.error('Error:', err.message);
}

CORS (Cross-Origin Resource Sharing)

Cuando el frontend (http://localhost:3000) hace peticiones al backend (http://localhost:8080), el navegador bloquea la petición por seguridad si los orígenes son distintos. El backend debe añadir cabeceras CORS para permitirlo:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

18. Tablas Comparativas

18.1 React vs Angular vs Vue

Característica React Angular Vue.js
Tipo Librería (solo UI) Framework completo Framework progresivo
Creador Meta (Facebook) Google Evan You (comunidad)
Lenguaje JavaScript/TypeScript TypeScript (obligatorio) JavaScript/TypeScript
Tipado Opcional (TS) Obligatorio (TS) Opcional (TS)
Sintaxis de template JSX HTML extendido con directivas Template HTML + Composition API
Gestión de estado useState, Context, Redux, Zustand Services + RxJS ref/reactive, Pinia, Vuex
Routing React Router (externo) RouterModule (integrado) Vue Router (oficial)
DOM Strategy Virtual DOM Change Detection (Zone.js) Virtual DOM + Reactivity Proxy
Curva de aprendizaje Media Alta Baja
Tamaño del bundle Pequeño (~40KB) Mayor (~130KB+) Pequeño (~20KB)
Empleo en mercado ★★★★★ ★★★★ ★★★
Ecosistema Enorme Grande Mediano
Ideal para SPAs, apps complejas, equipos Apps empresariales grandes Proyectos medianos, aprendizaje
Mobile React Native Ionic/NativeScript Capacitor/NativeScript
SSR Next.js Angular Universal Nuxt.js

18.2 Java/Spring Boot vs Node.js/Express (Backend)

Característica Java + Spring Boot Node.js + Express/NestJS
Lenguaje Java JavaScript / TypeScript
Tipado Estático, fuerte Dinámico (JS) / Estático (TS)
Paradigma POO principalmente Multi-paradigma (funcional/POO)
Modelo de concurrencia Multi-thread (hilos reales) Single-thread + Event Loop
Ideal para CPU-bound, transacciones complejas I/O-bound, real-time, APIs ligeras
Rendimiento I/O Bueno (con async) Excelente
Rendimiento CPU Excelente Limitado (bloquea Event Loop)
Arranque Lento (segundos) Rápido (milisegundos)
Memoria Mayor (JVM overhead) Menor
Madurez Muy alta (30 años) Media (15 años)
Ecosistema Maven Central, muy rico npm, enorme
Seguridad Spring Security (muy completo) Passport, JWT (más manual)
ORM Hibernate/JPA (maduro) Prisma, TypeORM, Sequelize
Microservicios Spring Cloud (potente) Node nativo (ligero)
Curva de aprendizaje Alta Media
Empresas que lo usan Bancos, grandes corporaciones Startups, Netflix, LinkedIn

18.3 JavaScript vs TypeScript

Característica JavaScript TypeScript
Tipo Lenguaje Superset de JavaScript
Tipado Dinámico, débil Estático, fuerte (opcional)
Verificación de errores En ejecución En compilación
Autocompletado IDE Básico Excelente
Refactoring Peligroso Seguro
Curva de aprendizaje Más baja Más alta
Build step No necesario Sí (tsc o bundler)
Compatibilidad Universal Compila a JS (compatible)
Ideal para Scripts, proyectos pequeños Proyectos medianos/grandes, equipos
Adopción actual Muy alta Creciendo rápidamente

18.4 Virtual DOM vs DOM Real

Característica DOM Real Virtual DOM
Ubicación Navegador (C++) Memoria JS
Velocidad de operación Lenta (reflow/repaint) Rápida (objetos JS)
Actualizaciones Inmediatas e individuales Batching + diff
Complejidad para el dev Alta (código manual) Baja (declarativo)
Overhead extra Ninguno Crear/comparar VDOM
Control Total (manual) Delegado al framework
Mejor para Scripts simples, animaciones Apps con mucho estado dinámico

18.5 Tabla resumen general de tecnologías

Tecnología Tipo Tipado Complejidad Uso principal Curva aprendizaje
HTML Lenguaje de marcado N/A Baja Estructura web ★☆☆☆☆
CSS Lenguaje de estilos N/A Media Presentación web ★★☆☆☆
JavaScript Lenguaje de prog. Dinámico Media-Alta Web interactiva, backend ★★★☆☆
TypeScript Superset JS Estático opcional Media-Alta JS tipado, proyectos grandes ★★★☆☆
JSON Formato de datos N/A Baja Intercambio de datos ★☆☆☆☆
React Librería UI Dinámica/Estática Media SPAs, UI complejas ★★★☆☆
Angular Framework completo Estático (TS obligatorio) Alta Apps empresariales ★★★★☆
Vue.js Framework progresivo Dinámica/Estática Baja-Media SPAs, aprendizaje ★★☆☆☆
Node.js Runtime JS Dinámica/Estática Media Backend I/O, APIs, real-time ★★★☆☆
Java Lenguaje de prog. Estático fuerte Alta Backend empresarial, sistemas ★★★★☆
Spring Boot Framework Java Estático fuerte Alta APIs REST empresariales ★★★★☆

📚 Resumen: Cómo se conecta todo

                    INTERNET
                       │
         ┌─────────────▼─────────────┐
         │         NAVEGADOR         │
         │  HTML → DOM               │
         │  CSS  → CSSOM → UI        │
         │  JS / TS                  │
         │    ├── React (VDOM)       │
         │    ├── Angular (CD)       │
         │    └── Vue (Proxy+VDOM)   │
         └─────────────┬─────────────┘
                       │  HTTP + JSON (REST API)
         ┌─────────────▼─────────────┐
         │           BACKEND         │
         │  Node.js (JS, Event Loop) │
         │    └── Express / NestJS   │
         │  ────────────────────     │
         │  Java (JVM, multi-thread) │
         │    └── Spring Boot (MVC)  │
         │         ├── Controller    │
         │         ├── Service       │
         │         └── Repository    │
         └─────────────┬─────────────┘
                       │  SQL / NoSQL
         ┌─────────────▼─────────────┐
         │        BASE DE DATOS      │
         │  PostgreSQL / MySQL       │
         │  MongoDB / Redis          │
         └───────────────────────────┘

🎓 Conceptos Clave para Recordar

Golden Rules del Frontend

  1. HTML = estructura (QUÉ hay), CSS = presentación (CÓMO se ve), JS = comportamiento (QUÉ hace).
  2. El DOM es una representación en memoria del HTML, no el HTML en sí.
  3. El Virtual DOM es una optimización para minimizar toques al DOM real.
  4. Los frameworks modernos trabajan con estado declarativo: defines qué quieres ver, no cómo actualizarlo.
  5. El Event Loop hace posible la asincronía en JavaScript con un solo hilo.

Golden Rules del Backend

  1. REST + JSON es el contrato estándar de comunicación frontend-backend.
  2. En Node.js, no bloquees el Event Loop con operaciones CPU-bound.
  3. En Spring Boot, la arquitectura Controller → Service → Repository mantiene el código limpio y testeable.
  4. La Inyección de Dependencias hace el código más testeable, modular y mantenible.
  5. La JVM hace que Java sea multiplataforma: compila una vez, ejecuta en cualquier parte.

Cuándo usar qué


Documento generado como guía de estudio de desarrollo web moderno y backend. Versión completa: HTML, CSS, JavaScript, TypeScript, DOM, Virtual DOM, JSON, React, Angular, Vue.js, Node.js, Java, Spring Boot.