Arquitectura de Componentes React Escalable
Componentes compuestos, tokens de diseño y bibliotecas tree-shakeable que tu equipo realmente adoptará.
A medida que las aplicaciones React crecen de prototipos a sistemas en producción, la arquitectura de componentes se convierte en la diferencia entre un codebase que escala con gracia y uno que colapsa bajo su propia complejidad. Compound components, design tokens y bibliotecas tree-shakeable forman un toolkit moderno para construir sistemas UI flexibles, performantes y mantenibles. Esta guía explora cada patrón con orientación práctica para equipos que publican aplicaciones React en producción en 2026.
El caso de los compound components
Los compound components son un patrón donde un componente padre gestiona estado y contexto compartidos mientras los componentes hijos manejan responsabilidades de renderizado específicas. Los usuarios componen la UI anidando subcomponentes con nombre en lugar de configurar todo mediante una interfaz plana de props. Este patrón aparece en design systems maduros — tabs, acordeones, menús y modales se benefician de la composición compound.
La ventaja principal es la ergonomía de la API. Compara un componente monolítico impulsado por props con una alternativa compound:
// Prop-driven — becomes unwieldy as features grow
<Tabs
items={[
{ label: "Overview", content: <Overview /> },
{ label: "Settings", content: <Settings />, disabled: true },
]}
defaultIndex={0}
onChange={handleTabChange}
variant="underline"
/>
// Compound — flexible, readable, extensible
<Tabs defaultValue="overview" onValueChange={handleTabChange}>
<Tabs.List>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="settings" disabled>Settings</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="overview">
<Overview />
</Tabs.Content>
<Tabs.Content value="settings">
<Settings />
</Tabs.Content>
</Tabs>
Los compound components se comunican mediante React Context. El padre crea un context provider con estado compartido — tab activo, estado abierto, valor seleccionado — y los componentes hijos consumen ese contexto para renderizar su porción de la UI. Este desacoplamiento significa que puedes agregar nuevos subcomponentes sin modificar la API del padre.
Implementar compound components
Comienza definiendo un contexto con una interfaz tipada. El componente raíz envuelve hijos en el provider y acepta props de configuración. Los subcomponentes leen del contexto y renderizan condicionalmente según el estado compartido.
- Exporta subcomponentes como propiedades estáticas en la raíz —
Tabs.List,Tabs.Trigger. - Valida la composición en desarrollo con mensajes de error útiles cuando los subcomponentes se usan fuera de su padre.
- Mantén valores de contexto estables con useMemo para prevenir re-renderizados innecesarios de todos los hijos.
- Soporta modos controlados y no controlados para máxima flexibilidad.
Design tokens como única fuente de verdad
Los design tokens son entidades con nombre que almacenan decisiones de diseño visual — colores, espaciado, tipografía, sombras, border radii — como valores agnósticos de plataforma. En lugar de hardcodear #3b82f6 o 16px en tus componentes, referencias tokens semánticos como color.action.primary o spacing.component.md.
Esta indirección ofrece beneficios tangibles a escala:
- Consistencia — Cada componente referencia los mismos valores de token, eliminando deriva visual.
- Theming — Intercambia valores de token para cambiar entre temas claro, oscuro y alto contraste.
- Alineación cross-platform — Exporta tokens a CSS, JavaScript, iOS y Android desde una única fuente.
- Colaboración diseño-dev — Diseñadores y desarrolladores comparten un vocabulario común.
// tokens.ts — semantic design tokens
export const tokens = {
color: {
surface: {
primary: "var(--color-surface-primary)",
secondary: "var(--color-surface-secondary)",
},
text: {
primary: "var(--color-text-primary)",
muted: "var(--color-text-muted)",
},
action: {
primary: "var(--color-action-primary)",
primaryHover: "var(--color-action-primary-hover)",
},
},
spacing: {
xs: "0.25rem",
sm: "0.5rem",
md: "1rem",
lg: "1.5rem",
xl: "2rem",
},
radius: {
sm: "0.25rem",
md: "0.5rem",
lg: "0.75rem",
full: "9999px",
},
} as const;
Define CSS custom properties en tu hoja de estilos global y refiérete a ellas mediante el objeto token en componentes. Cuando el equipo de diseño actualiza la paleta de marca, cambias valores en un lugar y cada componente se actualiza automáticamente.
Tree-shaking y bibliotecas modulares
El tamaño de bundle impacta directamente el rendimiento de la aplicación, especialmente en redes móviles. Tree-shaking elimina código muerto durante el proceso de build, pero solo si tu arquitectura de biblioteca lo soporta. Un export monolítico que re-exporta cada componente obliga a los bundlers a incluir toda la biblioteca incluso cuando usas un solo botón.
Estructura tu biblioteca de componentes para tree-shaking óptimo:
- Exporta cada componente desde su propio entry point de módulo.
- Marca tu paquete como sin side effects en
package.json. - Evita barrel files que re-exportan todo desde un único index.
- Usa formato ESM para bundlers modernos; proporciona CJS solo si se requiere soporte legacy.
- Mantén peer dependencies externas — React, React DOM y bibliotecas de estilizado no deben incluirse en el bundle.
// package.json — enable tree-shaking
{
"name": "@acme/ui",
"sideEffects": false,
"exports": {
"./button": "./dist/button/index.js",
"./input": "./dist/input/index.js",
"./modal": "./dist/modal/index.js",
"./tokens": "./dist/tokens/index.js"
}
}
// Consumer imports only what they need
import { Button } from "@acme/ui/button";
import { tokens } from "@acme/ui/tokens";
Mide el impacto con herramientas de análisis de bundle. Importa un solo componente y verifica que el bundle de producción excluya módulos no relacionados. Si toda tu biblioteca aparece en la salida, investiga barrel exports y declaraciones de side effects.
Estructura de carpetas y colocación
La estructura organizacional influye en qué tan rápido los desarrolladores encuentran y modifican componentes. El principio de colocación — mantener archivos relacionados juntos — reduce el cambio de contexto y hace que los componentes sean unidades autocontenidas que pueden moverse, probarse y eliminarse independientemente.
Una estructura de carpetas escalable para una biblioteca de componentes:
src/components/Button/Button.tsx— Implementación del componente.src/components/Button/Button.test.tsx— Pruebas unitarias colocadas con el componente.src/components/Button/Button.stories.tsx— Documentación Storybook.src/components/Button/index.ts— Superficie de export pública.src/tokens/— Definiciones compartidas de design tokens.src/hooks/— Hooks compartidos usados en múltiples componentes.
Evita organizar por tipo (components/, hooks/, utils/ en el nivel superior de cada funcionalidad). En su lugar, agrupa por dominio de funcionalidad al construir arquitectura a nivel de aplicación, y por componente al construir una biblioteca compartida.
Composición sobre configuración
El hilo conductor que conecta compound components, design tokens y módulos tree-shakeable es una filosofía: favorecer composición sobre configuración. Los componentes deben ser pequeños, enfocados y combinables en lugar de widgets monolíticos con docenas de props que controlan cada variante visual.
Aplica el principio open-closed — los componentes están abiertos para extensión mediante composición pero cerrados para modificación. En lugar de agregar una prop showIcon a un botón, acepta un icono como hijo o slot. En lugar de una prop size con cinco valores enum, expone CSS custom properties que los consumidores sobrescriben.
Este enfoque produce bibliotecas de componentes que envejecen bien. Los nuevos requisitos se satisfacen componiendo primitivos existentes en lugar de modificar componentes probados en batalla y arriesgar regresiones en todo el sistema.
Documentación y adopción
Los patrones de arquitectura solo entregan valor cuando el equipo los comprende y adopta consistentemente. Invierte en Storybook o una plataforma de documentación similar que muestre composición de compound components, uso de tokens y patrones de import. Escribe guías de contribución que expliquen cuándo crear un componente nuevo versus extender uno existente.
Registra architecture decision records para elecciones estructurales significativas — por qué elegiste compound components sobre render props, por qué los tokens viven en CSS custom properties en lugar de un objeto theme JavaScript. Los futuros miembros del equipo heredarán estas decisiones y necesitarán contexto para mantener consistencia.
La arquitectura escalable de componentes React no se trata de aplicar todos los patrones simultáneamente. Se trata de elegir las abstracciones correctas para el tamaño de tu equipo, la complejidad de tu aplicación y tus restricciones de rendimiento. Los compound components manejan composición UI flexible, los design tokens imponen consistencia visual, y los módulos tree-shakeable mantienen bundles ligeros — juntos forman una base que soporta crecimiento de diez componentes a diez mil.