145 lines
7.1 KiB
Markdown
145 lines
7.1 KiB
Markdown
|
|
# Arquitectura frontend
|
||
|
|
|
||
|
|
> Referencia especializada del skill `rdx-solid`. Consulta [arquitectura.md](arquitectura.md) y respeta las convenciones de `SKILL.md` y `AGENTS.md`.
|
||
|
|
|
||
|
|
## 1. Propósito
|
||
|
|
|
||
|
|
Organizar interfaces mantenibles, accesibles y verificables. Los ejemplos están orientados a React y TypeScript; adapta los criterios al framework utilizado. No reproduzcas automáticamente las capas del backend dentro del navegador.
|
||
|
|
|
||
|
|
## 2. Partir de la estructura del proyecto
|
||
|
|
|
||
|
|
Antes de modificar componentes, examina: enrutado, diseño visual, biblioteca de UI, convención de carpetas, gestión de estado, formularios, consumo de APIs, i18n y pruebas. Respeta los límites existentes y evita migraciones de arquitectura no solicitadas.
|
||
|
|
|
||
|
|
## 3. Organización por funcionalidades
|
||
|
|
|
||
|
|
Agrupa componentes, hooks, servicios y tipos de una funcionalidad cuando ello reduzca la dispersión. No crees todas las subcarpetas por defecto.
|
||
|
|
|
||
|
|
```text
|
||
|
|
src/
|
||
|
|
features/
|
||
|
|
orders/
|
||
|
|
components/
|
||
|
|
order-list.tsx
|
||
|
|
order-form-dialog.tsx
|
||
|
|
hooks/
|
||
|
|
use-orders.ts
|
||
|
|
api/
|
||
|
|
orders-client.ts
|
||
|
|
index.ts
|
||
|
|
shared/
|
||
|
|
ui/
|
||
|
|
hooks/
|
||
|
|
```
|
||
|
|
|
||
|
|
- `shared/` contiene elementos realmente reutilizables, no un cajón para código sin dueño.
|
||
|
|
- Mantén públicas solo las APIs que otros módulos deban consumir; evita importar detalles internos entre funcionalidades.
|
||
|
|
- No crees un componente por cada etiqueta HTML: la extracción debe representar una responsabilidad, reutilización o complejidad significativa.
|
||
|
|
- No concentres numerosos componentes independientes en un solo archivo si dificulta comprenderlos o mantenerlos.
|
||
|
|
- Modales y diálogos con lógica propia deben tender a componentes separados; un cuadro trivial puede permanecer local cuando resulte más claro.
|
||
|
|
|
||
|
|
## 4. Componentes y responsabilidades
|
||
|
|
|
||
|
|
- Prefiere composición sobre jerarquías de herencia de componentes.
|
||
|
|
- Mantén la lógica compleja de dominio fuera de la representación visual.
|
||
|
|
- Utiliza props explícitas y contratos de componentes comprensibles.
|
||
|
|
- Evita convertir cada componente en un conjunto de capas y controladores.
|
||
|
|
- Extrae hooks cuando encapsulen lógica reactiva reutilizable o significativa; no para ocultar una única llamada simple.
|
||
|
|
- No introduzcas renderizado derivado con estado duplicado cuando pueda calcularse a partir de props o estado existente.
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
interface OrderSummaryProps {
|
||
|
|
order: OrderSummary;
|
||
|
|
onSelect: (orderId: string) => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function OrderSummaryCard({ order, onSelect }: OrderSummaryProps) {
|
||
|
|
return (
|
||
|
|
<article>
|
||
|
|
<h3>{order.reference}</h3>
|
||
|
|
<button type="button" onClick={() => onSelect(order.id)}>
|
||
|
|
Ver pedido
|
||
|
|
</button>
|
||
|
|
</article>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
El ejemplo presupone un tipo de presentación `OrderSummary` y una interfaz accesible que puede requerir más detalles según el diseño.
|
||
|
|
|
||
|
|
## 5. Estado y datos remotos
|
||
|
|
|
||
|
|
Distingue:
|
||
|
|
|
||
|
|
- **Estado local:** interacción de un componente o pequeño subárbol.
|
||
|
|
- **Estado compartido de UI:** necesidades de varios componentes relacionados.
|
||
|
|
- **Estado remoto:** datos obtenidos del servidor, con carga, error y actualización.
|
||
|
|
- **Estado derivado:** valores calculables que normalmente no deben almacenarse por duplicado.
|
||
|
|
|
||
|
|
No introduzcas un gestor global de estado para resolver un formulario aislado. Para datos remotos, reutiliza las bibliotecas de consulta, caché e invalidación que ya utiliza el proyecto. Evita duplicar en estado global la caché del servidor sin motivo.
|
||
|
|
|
||
|
|
Controla carreras entre solicitudes, cancelación, refresco y estados vacíos cuando corresponda.
|
||
|
|
|
||
|
|
## 6. Formularios y cuadros de diálogo
|
||
|
|
|
||
|
|
- Conserva validaciones de experiencia de usuario en frontend y la validación autoritativa en backend.
|
||
|
|
- Muestra errores comprensibles y asociados al campo o acción pertinente.
|
||
|
|
- Considera guardado pendiente, reintentos, cambios sin guardar y envío duplicado.
|
||
|
|
- Mantén los formularios complejos y modales con responsabilidad propia en componentes independientes.
|
||
|
|
- Respeta foco, navegación por teclado, cierre, etiquetas y mensajes accesibles.
|
||
|
|
- Reutiliza los componentes del sistema de diseño y no edites paquetes de terceros para implementar personalizaciones locales.
|
||
|
|
|
||
|
|
## 7. Acceso a APIs y contratos
|
||
|
|
|
||
|
|
- Centraliza donde corresponda la adaptación de respuestas, autenticación y errores de transporte.
|
||
|
|
- No expongas directamente modelos internos de la base de datos como modelos de UI.
|
||
|
|
- Maneja explícitamente carga, vacío, éxito y error.
|
||
|
|
- No confíes en tipos estáticos para garantizar la forma de datos remotos en ejecución.
|
||
|
|
- Evita mezclar llamadas HTTP y transformación compleja dentro de componentes de presentación.
|
||
|
|
- No asumas que frontend y backend se actualizan al mismo tiempo; mantén compatibilidad según sus contratos.
|
||
|
|
|
||
|
|
Consulta [arquitectura-shared.md](arquitectura-shared.md) para DTO, tipos, esquemas y generación de clientes.
|
||
|
|
|
||
|
|
## 8. Accesibilidad, i18n y seguridad
|
||
|
|
|
||
|
|
- Utiliza HTML semántico, etiquetas, navegación por teclado y gestión de foco.
|
||
|
|
- Prueba estados accesibles de carga, error y modales.
|
||
|
|
- No insertes textos literales en áreas gobernadas por i18n; conserva `es` y `en` cuando sean idiomas soportados.
|
||
|
|
- Trata contenido no confiable de forma segura; evita inyección de HTML.
|
||
|
|
- No almacenes secretos de servidor en código distribuido al navegador.
|
||
|
|
- La ocultación de botones no sustituye la autorización del backend.
|
||
|
|
|
||
|
|
## 9. Rendimiento
|
||
|
|
|
||
|
|
Optimiza basándote en evidencia: identifica re-renderizados costosos, bundles grandes, rutas pesadas y solicitudes redundantes. No añadas memoización a todos los componentes por rutina. Utiliza división de código, virtualización o carga diferida cuando el volumen real lo requiera. Mantén claves estables en listas.
|
||
|
|
|
||
|
|
## 10. Pruebas
|
||
|
|
|
||
|
|
- Prueba comportamientos percibidos por el usuario en lugar de detalles de implementación.
|
||
|
|
- Comprueba formularios, validaciones, errores, roles y accesibilidad relevante.
|
||
|
|
- Utiliza pruebas de componentes e integración para flujos locales; E2E para recorridos críticos.
|
||
|
|
- No hagas que pruebas de UI dependan innecesariamente de detalles internos de hooks.
|
||
|
|
- Verifica los contratos de API cuando cambien.
|
||
|
|
|
||
|
|
## 11. Señales de alerta
|
||
|
|
|
||
|
|
- Componentes enormes con estado, transporte y reglas mezclados.
|
||
|
|
- Estado remoto duplicado en varios almacenes.
|
||
|
|
- Hooks extraídos sin responsabilidad concreta.
|
||
|
|
- `shared/` que contiene reglas exclusivas de una funcionalidad.
|
||
|
|
- Múltiples diálogos complejos incrustados en un componente contenedor.
|
||
|
|
- Uso de `useEffect` para derivar valores calculables directamente.
|
||
|
|
- Lógica de autorización exclusivamente en frontend.
|
||
|
|
- Optimizaciones preventivas que dificultan la lectura.
|
||
|
|
|
||
|
|
## 12. Lista de comprobación
|
||
|
|
|
||
|
|
- [ ] ¿La modificación respeta las convenciones de React y del repositorio?
|
||
|
|
- [ ] ¿Cada componente y hook mantiene una responsabilidad clara?
|
||
|
|
- [ ] ¿El estado pertenece al ámbito apropiado?
|
||
|
|
- [ ] ¿Los formularios y diálogos son accesibles y verificables?
|
||
|
|
- [ ] ¿Se respetan i18n, seguridad y contratos de API?
|
||
|
|
- [ ] ¿He evitado abstracciones o librerías nuevas sin necesidad?
|
||
|
|
- [ ] ¿Las pruebas cubren el comportamiento modificado?
|
||
|
|
|
||
|
|
**Principio final:** el frontend debe expresar flujos de usuario claros sin convertir la interfaz en un conjunto de abstracciones innecesarias.
|