Teoría del frontend¶
Antes de escribir una línea de Angular conviene tener claro qué problema resuelve el frontend, qué formas existen de construirlo y qué ocurre dentro del navegador cuando una SPA está funcionando. Esta página es el marco conceptual de toda la sección.
1. Frontend y backend: una frontera de responsabilidades¶
Una aplicación web se divide en dos grandes lados separados por la red:
| Frontend | Backend | |
|---|---|---|
| Dónde se ejecuta | En el navegador del usuario | En el servidor |
| Responsabilidad | Presentar información, capturar acciones, dar retroalimentación | Aplicar reglas de negocio, persistir datos, autorizar |
| Lenguajes | HTML, CSS, JavaScript / TypeScript | Java, Python, C#, Node.js… |
| Quién lo controla | El usuario (puede ver y modificar el código) | La organización |
| Pregunta que responde | ¿Cómo lo ve y lo usa la persona? | ¿Es correcto, está permitido y queda guardado? |
flowchart LR
U((Usuario)) <--> F["Frontend<br/>presentación · interacción · estado de la interfaz"]
F <-- "HTTP · JSON" --> B["Backend<br/>reglas · seguridad · persistencia"]
B <--> DB[(Base de datos)]
Regla de oro
Todo lo que corre en el navegador está en manos del usuario: puede leerlo, modificarlo o saltárselo. Por eso el frontend nunca es el lugar de la seguridad ni de las reglas definitivas; solo las anticipa para mejorar la experiencia. La última palabra la tiene el backend.
¿Qué hace exactamente un frontend?¶
- Presentar datos de forma comprensible (tablas, tarjetas, gráficos, mapas).
- Capturar acciones e información del usuario (clics, formularios, búsquedas).
- Validar de forma temprana para dar retroalimentación inmediata.
- Comunicarse con una o varias APIs.
- Gestionar el estado de la interfaz: qué pantalla está activa, qué se está cargando, qué falló.
- Navegar entre vistas.
- Ser accesible, rápido y funcionar en distintos dispositivos.
2. Modelos de renderizado: ¿quién construye el HTML?¶
La decisión arquitectónica más importante de un frontend es dónde y cuándo se genera el HTML que ve el usuario.
MPA / Server-Side Rendering clásico¶
Multi-Page Application. Cada URL es una página distinta que el servidor construye en cada petición. Es lo que hicimos con Thymeleaf; también JSP, PHP, Django o ASP.NET MVC.
sequenceDiagram
participant N as Navegador
participant S as Servidor
N->>S: GET /students
S->>S: consulta BD + plantilla
S-->>N: HTML completo
N->>S: GET /students/42 (clic en enlace)
S-->>N: HTML completo (recarga total)
SPA / Client-Side Rendering (CSR)¶
Single Page Application. El servidor entrega un HTML casi vacío y un paquete de JavaScript; el navegador construye todas las vistas y solo pide datos a la API. Es el modelo de Angular, React o Vue en su forma básica.
sequenceDiagram
participant N as Navegador
participant W as Servidor web
participant A as API REST
N->>W: GET / (una sola vez)
W-->>N: index.html + main.js
N->>N: Angular arranca y dibuja la vista
N->>A: GET /api/students
A-->>N: JSON
N->>N: clic → Router cambia la vista (sin recarga)
N->>A: GET /api/students/42
A-->>N: JSON
SSR con hidratación¶
Híbrido moderno: el servidor ejecuta el mismo código del framework para entregar HTML ya armado (primera carga rápida y buena para buscadores), y luego el navegador "hidrata" esa página, es decir, le conecta los eventos y la convierte en SPA. Angular lo ofrece como Angular SSR; en React existe Next.js y en Vue, Nuxt.
SSG: generación estática¶
El HTML de todas las páginas se genera una sola vez, al compilar, y se publica como archivos estáticos. Ideal para contenido que cambia poco: blogs, documentación… este mismo sitio se genera así con MkDocs.
Comparación¶
| Modelo | Quién arma el HTML | Cuándo | Primera carga | Navegación | SEO | Ejemplos |
|---|---|---|---|---|---|---|
| MPA / SSR clásico | Servidor | En cada petición | Rápida | Recarga completa | Excelente | Thymeleaf, JSP, PHP |
| SPA / CSR | Navegador | En ejecución | Más lenta (descarga JS) | Fluida, sin recarga | Requiere ayuda | Angular, React, Vue |
| SSR + hidratación | Servidor y luego navegador | Petición + ejecución | Rápida | Fluida | Excelente | Angular SSR, Next.js, Nuxt |
| SSG | Herramienta de build | Al compilar | Muy rápida | Recarga (o SPA) | Excelente | MkDocs, Astro, Hugo |
No hay un modelo ganador
La elección depende del producto. Un portal de noticias necesita SEO y primera carga rápida (SSR/SSG). Un sistema administrativo detrás de un login —como el caso de estudio o el proyecto del curso— privilegia la interacción fluida: ahí una SPA es la opción natural.
3. ¿Cómo funciona una SPA por dentro?¶
3.1 Una sola página, muchas vistas¶
El navegador solo carga index.html una vez. Dentro hay un punto de montaje (<app-root>), y el framework reemplaza su contenido según la vista activa. Lo que se mantiene (menú, encabezado) no se vuelve a dibujar.
3.2 Enrutamiento en el cliente¶
¿Cómo cambia la URL sin pedir otra página al servidor? Con la History API del navegador:
history.pushState({}, '', '/students/42'); // cambia la URL, NO hace petición
window.addEventListener('popstate', () => { // botón "atrás"
// el router lee location.pathname y dibuja la vista correspondiente
});
El router del framework envuelve este mecanismo: intercepta los clics en enlaces internos, actualiza la URL con pushState y decide qué componente mostrar.
flowchart LR
C[Clic en routerLink] --> P["history.pushState('/students/42')"]
P --> R[Router busca la ruta que coincide]
R --> V[Destruye la vista anterior<br/>y crea StudentDetailComponent]
V --> D[El componente pide datos a la API]
Consecuencia para el despliegue
Si el usuario recarga /students/42, la petición sí llega al servidor web, que no tiene ese archivo. Por eso el servidor debe responder siempre index.html para rutas desconocidas (fallback); Angular arranca y resuelve la ruta en el cliente.
3.3 Reactividad: del dato a la pantalla¶
En JavaScript actualizábamos el DOM a mano. Un framework invierte esa responsabilidad: declaramos cómo debe verse la vista en función del estado, y el framework se encarga de sincronizarla cuando el estado cambia.
flowchart LR
E[Evento<br/>clic, respuesta HTTP] --> S[Cambia el estado]
S --> F[El framework detecta el cambio]
F --> V[Actualiza solo las partes<br/>del DOM afectadas]
V --> E
Cada framework detecta los cambios de forma distinta:
| Estrategia | Idea | Quién la usa |
|---|---|---|
| Detección de cambios | Tras cada evento, revisar los bindings del árbol de componentes | Angular (Zone.js) |
| Virtual DOM | Generar una copia ligera del DOM, compararla con la anterior (diffing) y aplicar solo diferencias | React, Vue |
| Signals / reactividad fina | Cada valor sabe qué partes de la vista dependen de él y solo esas se actualizan | Angular (signals), Solid, Vue, Svelte |
3.4 Estado de la interfaz¶
El estado es toda la información que determina qué se ve en un momento dado. Conviene distinguir sus tipos:
| Tipo de estado | Ejemplo | Dónde vive en Angular |
|---|---|---|
| Local de un componente | Un menú desplegado, el texto de un campo | Propiedad o signal del componente |
| Compartido | Usuario autenticado, proyecto seleccionado | Servicio providedIn: 'root' |
| En la URL | /students/42?page=2 |
Router (parámetros) |
| Del servidor | La lista de estudiantes | API; el frontend guarda una copia temporal |
La URL también es estado
Si una vista depende de un filtro o una página, ponerlo en la URL permite recargar, compartir el enlace y usar el botón atrás sin perder el contexto.
4. Arquitectura basada en componentes¶
Todos los frameworks modernos coinciden en una idea: la interfaz se construye como un árbol de componentes, cada uno con su propia estructura, estilo y comportamiento.
flowchart TD
A[App] --> H[Header]
A --> M[Menú]
A --> P[Página: listado de estudiantes]
P --> F[Filtro]
P --> L[Lista]
L --> C1[Tarjeta]
L --> C2[Tarjeta]
L --> C3[Tarjeta]
Principios que guían el diseño:
- Responsabilidad única: cada componente resuelve una necesidad visual concreta.
- Encapsulamiento: sus estilos y su lógica no se filtran a otros componentes.
- Composición: pantallas complejas se arman combinando piezas simples.
- Flujo de datos unidireccional: los datos bajan (de padre a hijo); los eventos suben (de hijo a padre).
- Contenedores y presentacionales: unos componentes coordinan (piden datos, deciden), otros solo muestran lo que reciben. Los segundos son los más reutilizables.
5. El ecosistema de herramientas¶
Un proyecto frontend moderno no se escribe directamente en el JavaScript que ejecuta el navegador. Pasa por una cadena de construcción (build):
flowchart LR
TS["Código fuente<br/>TypeScript · HTML · CSS"] --> T["Compilar / transpilar<br/>TS → JS"]
T --> B["Empaquetar (bundle)<br/>muchos archivos → pocos"]
B --> O["Optimizar<br/>tree-shaking · minificar"]
O --> D["dist/<br/>archivos estáticos"]
| Concepto | Qué significa |
|---|---|
| npm | Gestor de paquetes: descarga las dependencias declaradas en package.json a node_modules/ |
| Transpilar | Convertir TypeScript (o JS moderno) a JavaScript que el navegador entiende |
| Bundler | Une cientos de módulos en unos pocos archivos (Angular usa esbuild / Vite) |
| Tree-shaking | Eliminar el código importado que nunca se usa |
| Minificar | Quitar espacios y acortar nombres para reducir el tamaño |
| Lazy loading | Dividir el bundle en partes (chunks) que se descargan solo cuando se necesitan |
| Dev server | Servidor local con recarga automática al guardar (ng serve) |
El resultado de ng build son archivos estáticos: se pueden publicar en cualquier servidor web (nginx, un bucket, un CDN), sin Java ni Node en producción.
Frameworks y librerías¶
| Herramienta | Tipo | Lenguaje | Características |
|---|---|---|---|
| Angular | Framework completo | TypeScript | Estructura definida: router, HTTP, formularios, DI, CLI. Muy usado en entornos empresariales |
| React | Librería de UI | JavaScript / TS (JSX) | Solo la vista; el resto (router, estado) se elige aparte. Ecosistema enorme |
| Vue | Framework progresivo | JavaScript / TS | Curva de aprendizaje suave; se puede adoptar por partes |
| Svelte | Compilador | JavaScript / TS | Convierte componentes en JS optimizado al compilar, sin runtime pesado |
¿Por qué Angular en este curso?
Porque es opinado: impone una forma de organizar el código (componentes, modelos, servicios, rutas) muy parecida a las capas que ya construimos en Spring Boot. Los conceptos —componentes, reactividad, routing, consumo de APIs— se transfieren a cualquier otro framework.
6. Calidad de un frontend¶
Que la aplicación "funcione" no es suficiente. Un buen frontend se evalúa también en estas dimensiones:
Rendimiento¶
| Métrica (Core Web Vitals) | Qué mide | Objetivo |
|---|---|---|
| LCP · Largest Contentful Paint | Cuánto tarda en verse el contenido principal | < 2,5 s |
| INP · Interaction to Next Paint | Cuánto tarda la interfaz en responder a una interacción | < 200 ms |
| CLS · Cumulative Layout Shift | Cuánto "salta" el contenido mientras carga | < 0,1 |
Buenas prácticas: carga perezosa de rutas, imágenes optimizadas, no descargar datos que no se muestran, paginar listas largas.
Accesibilidad (a11y)¶
La aplicación debe poder usarse con teclado, lector de pantalla o con baja visión:
- Usar HTML semántico (
<button>,<nav>,<main>,<label>) en lugar de<div>para todo. - Asociar cada campo con su
<label>. - Contraste de color suficiente y no comunicar información solo con color.
- Que todo lo que se hace con el mouse se pueda hacer con el teclado.
Seguridad en el navegador¶
| Riesgo | Qué es | Cómo se mitiga |
|---|---|---|
| XSS (Cross-Site Scripting) | Inyectar JavaScript malicioso a través de datos mostrados en la página | Angular escapa automáticamente {{ }}; evitar innerHTML con datos no confiables |
| CSRF | Que otro sitio haga peticiones en nombre del usuario autenticado | Tokens en cabecera (Authorization: Bearer) en lugar de solo cookies; protección CSRF en el backend |
| CORS | Política del navegador que bloquea peticiones a otro origen salvo autorización | El backend declara qué orígenes acepta |
| Exposición de secretos | Poner claves o contraseñas en el código del frontend | Nunca: todo el código del frontend es público |
Experiencia de usuario¶
Toda operación asíncrona tiene cuatro estados que la interfaz debe representar: inactivo, cargando, éxito y error. Una pantalla que se queda en blanco mientras carga o que no explica un fallo se percibe como rota, aunque el backend funcione. (Ver Excepciones.)
7. Glosario rápido¶
| Término | Definición breve |
|---|---|
| DOM | Representación en árbol del documento HTML que el navegador mantiene en memoria y que JavaScript puede modificar |
| SPA | Aplicación que carga una sola página y cambia las vistas en el navegador |
| MPA | Aplicación donde cada navegación pide una página completa al servidor |
| CSR / SSR / SSG | Renderizado en cliente / en servidor / al compilar |
| Hidratación | Conectar eventos y estado a un HTML que llegó ya generado desde el servidor |
| Componente | Pieza reutilizable de interfaz con su HTML, estilos y lógica |
| Binding | Conexión automática entre un dato y la vista |
| Estado | Información que determina qué se muestra en un momento dado |
| Router | Pieza que asocia URLs con vistas sin recargar la página |
| API REST | Interfaz HTTP que expone recursos en formato JSON |
| Bundle | Archivo(s) JavaScript resultante(s) de empaquetar la aplicación |
| Observable | Fuente de valores asíncronos a la que uno se suscribe (RxJS) |
| Signal | Valor reactivo que notifica a Angular cuando cambia |
Pregunta de reflexión
El proyecto del curso es un sistema de gestión de procesos con login, roles y edición de diagramas. ¿Qué modelo de renderizado elegirías y por qué? ¿Qué parte del sistema podría beneficiarse de otro modelo (por ejemplo, una página pública de presentación)?
Siguiente: Generalidades de Angular.