Arquitectura y Escalado
Mono-repos, versionado, distribución y escalado de sistemas de diseño entre equipos
Escalando Sistemas de Diseño
A medida que tu sistema de diseño crece más allá de un solo equipo, necesitas arquitectura sólida para versionado, distribución y colaboración multi-equipo. Un sistema bien arquitecturado puede servir a cientos de desarrolladores en docenas de proyectos.
🏗️ Decisiones de Arquitectura
Todos los paquetes en un repositorio (Turborepo, Nx)
Repositorios separados por paquete
Todo empaquetado junto
Propiedad distribuida entre equipos
Configuración de Monorepo con Turborepo
# Crear un nuevo Turborepo
npx create-turbo@latest my-design-system
# Estructura de carpetas
my-design-system/
├── apps/
│ ├── docs/ # Storybook o sitio de documentación
│ └── playground/ # Aplicación de prueba/demostración
├── packages/
│ ├── tokens/ # Tokens de diseño
│ ├── ui/ # Componentes React
│ ├── utils/ # Utilidades compartidas
│ └── config/ # Configuraciones compartidas (ESLint, TypeScript)
├── turbo.json
├── package.json
└── pnpm-workspace.yaml
# turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {},
"test": {
"dependsOn": ["build"]
}
}
}
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
# Ejecutar todas las compilaciones
pnpm turbo run build
# Ejecutar solo paquetes cambiados
pnpm turbo run build --filter=...[HEAD~1]
Estructura de Paquete
// packages/ui/package.json
{
"name": "@acme/ui",
"version": "1.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./button": {
"import": "./dist/button.mjs",
"require": "./dist/button.js",
"types": "./dist/button.d.ts"
}
},
"sideEffects": ["**/*.css"],
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@acme/tokens": "workspace:*",
"tsup": "^7.0.0",
"typescript": "^5.0.0"
},
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
}
}
// packages/ui/src/index.ts
export * from './Button';
export * from './Card';
export * from './Input';
// ...
// packages/ui/tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts', 'src/button.ts'],
format: ['cjs', 'esm'],
dts: true,
splitting: true,
clean: true,
treeshake: true,
external: ['react', 'react-dom'],
});
Versionado con Changesets
# Instalar changesets
pnpm add -Dw @changesets/cli
# Inicializar
pnpm changeset init
# Cuando hagas un cambio, agrega un changeset
pnpm changeset
# Esto pregunta: ¿Qué paquetes cambiaron? ¿Mayor/menor/parche? ¿Descripción?
# Crea un archivo como:
# .changeset/brave-eagles-dance.md
---
"@acme/ui": minor
"@acme/tokens": patch
---
Se agregó nuevo componente Avatar con soporte de imagen de respaldo.
# Flujo de trabajo de versionado
pnpm changeset version # Aumenta versiones, actualiza CHANGELOG
pnpm changeset publish # Publica a npm
# En CI (GitHub Actions)
- name: Crear PR de Release o Publicar
uses: changesets/action@v1
with:
publish: pnpm changeset publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Publicación a npm
# .npmrc para registros privados
@acme:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
# O usa el registro público de npm
# Asegúrate de que package.json tenga:
{
"name": "@acme/ui",
"publishConfig": {
"access": "public"
}
}
# Script de compilación y publicación
# package.json (raíz)
{
"scripts": {
"release": "pnpm build && pnpm changeset publish"
}
}
# Flujo de trabajo de GitHub Actions
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- run: pnpm install
- run: pnpm build
- name: Publicar
uses: changesets/action@v1
with:
publish: pnpm changeset publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Contribución Multi-Equipo
// Archivo CODEOWNERS para GitHub
# .github/CODEOWNERS
# El equipo central posee todo por defecto
* @acme/design-system-core
# Propiedad de componente específico
/packages/ui/src/data-table/ @acme/data-team
/packages/ui/src/charts/ @acme/analytics-team
/packages/tokens/ @acme/design-team
# Directrices de Contribución (CONTRIBUTING.md)
## Agregar un Nuevo Componente
1. Crea un issue de propuesta usando la plantilla
2. Obtén aprobación del equipo design-system-core
3. Crea componente siguiendo patrones en /packages/ui/src/Button
4. Agrega historias de Storybook
5. Agrega pruebas unitarias
6. Agrega changeset
7. Abre PR y solicita revisión
## Lista de Verificación de Componente
- [ ] Tipos TypeScript exportados
- [ ] Historia de Storybook con todas las variantes
- [ ] Pruebas unitarias con >80% de cobertura
- [ ] Accesibilidad probada (teclado + lector de pantalla)
- [ ] Documentación en MDX de Storybook
- [ ] Changeset agregado
Consumiendo Sistemas de Diseño
# Instalando el sistema de diseño
npm install @acme/ui @acme/tokens
# En tu aplicación
import { Button, Card } from '@acme/ui';
import '@acme/ui/styles.css'; // O importar tokens
// Tree-shaking: solo importa lo que usas
import { Button } from '@acme/ui/button';
// Estrategias de fijación de versión
// package.json
{
"dependencies": {
// Versión exacta (más segura, pero actualizaciones manuales)
"@acme/ui": "2.1.0",
// Caret: permite actualizaciones menores (recomendado)
"@acme/ui": "^2.1.0",
// Tilde: permite solo actualizaciones de parche
"@acme/ui": "~2.1.0"
}
}
// Configuración de Renovate para auto-actualizaciones
// renovate.json
{
"extends": ["config:base"],
"packageRules": [
{
"matchPackagePatterns": ["@acme/*"],
"automerge": true,
"automergeType": "branch"
}
]
}
Herramientas de Sistema de Diseño
Sistema de compilación de monorepo de alto rendimiento
Kit de herramientas de monorepo con todas las características y generadores
Empaquetador TypeScript sin configuración impulsado por esbuild
Gestión de versionado y changelog para monorepos
Pruebas visuales y revisión para componentes de interfaz
💡 Consejos de Escalado
- • Comienza pequeño: no sobre-ingenierices temprano
- • Establece propiedad clara con CODEOWNERS
- • Usa versionado semántico estrictamente
- • Documenta cambios que rompen compatibilidad a fondo
- • Proporciona guías de migración para versiones mayores
- • Configura pruebas de regresión visual automatizadas
- • Crea directrices de contribución temprano
- • Usa banderas de características para despliegues graduales