Monorepo moderno para proyectos React, optimizado para producción con Vite 8 (Rolldown + Oxc), TurboRepo y pnpm workspaces. Incluye empaquetado de librerías con tsdown, configuraciones de seguridad, rendimiento optimizado y mejores prácticas a junio de 2026.
- Vite 8 + Rolldown: Bundler en Rust (drop-in de Rollup) para builds hasta 10x más rápidos
- Oxc: Transformador y minificador en Rust (reemplaza a esbuild, 2x más rápido)
- Lightning CSS: Minificador CSS en Rust (reemplaza a esbuild para CSS)
- Code splitting nativo:
codeSplitting.nativeGroupsagrupa vendor chunks por regex - Tree-shaking agresivo:
moduleSideEffects: false,propertyReadSideEffects: false - Drop automático:
console.*ydebuggereliminados en producción via Oxc
- Headers de seguridad: X-Content-Type-Options, X-Frame-Options, CSP ready
- Scripts bloqueados:
ignore-scripts=trueen.npmrc(anti supply-chain attacks) - Variables de entorno tipadas: Autogeneradas con autocompletado TypeScript
- HTTPS forzado: Strict-Transport-Security configurado
- Auditoría de dependencias:
pnpm auditintegrado en CI
- Alias automáticos: Los imports de paquetes internos se generan desde
paquetes/ - tsdown: Empaquetador de librerías TS powered by Rolldown (más rápido que tsup)
- Oxc (oxlint + oxfmt): Linter 50-100x más rápido que ESLint, formatter 30x más rápido que Prettier
- Turborepo: Caché inteligente para builds incrementales
- TypeScript estricto: Todas las verificaciones de tipos habilitadas
- React 19: Última versión con Actions, Server Components y Compiler ready
- Tailwind CSS v4: Nuevo motor Oxide escrito en Rust
- React Query 5: Data fetching con caché automático
- Zustand 5: Estado global minimalista
- React Router 7: Routing con loaders y data API
- Node.js >= 24.11.0 (Vite 8 y tsdown requieren Node 22.18+, Rolldown recomienda 24+)
- pnpm >= 10.0.0
# Verificar versiones
node --version # v24.x.x
pnpm --version # 10.x.x💡 Usa
nvm usesi tienes.nvmrcconfigurado en tu proyecto.
# 1. Clona el repositorio
git clone https://github.com/cristiancastineiras/plantilla-react-monorepo.git
cd plantilla-react-monorepo
# 2. Instala dependencias (pnpm.lock se respeta)
pnpm install
# 3. Inicia el servidor de desarrollo
pnpm devLa app estará disponible en http://localhost:4200/plantilla/ (puerto configurable vía VITE_PUERTO).
| Comando | Descripción |
|---|---|
pnpm dev |
Inicia servidor de desarrollo con HMR (todas las apps) |
pnpm build |
Build de producción optimizado de todo el monorepo |
pnpm build:webapp |
Build solo de la webapp |
pnpm preview |
Previsualiza el build de producción |
pnpm lint |
Verifica código con oxlint (todos los paquetes) |
pnpm lint:fix |
Corrige errores automáticamente |
pnpm format |
Formatea todo el código con oxfmt |
pnpm format:check |
Verifica formato sin escribir (para CI) |
pnpm typecheck |
Verifica tipos TypeScript en todo el monorepo |
pnpm check |
Ejecuta lint + format:check |
pnpm clean |
Limpia carpetas de cache y build |
pnpm clean:all |
Limpieza total + reinstalación de dependencias |
pnpm audit |
Auditoría de seguridad de dependencias |
pnpm deps:check |
Verifica dependencias desactualizadas |
pnpm deps:update |
Actualiza dependencias a latest |
Cada paquete en paquetes/* expone:
pnpm --filter @paquetes/componentes build # Build producción
pnpm --filter @paquetes/componentes dev # Build en watch mode
pnpm --filter @paquetes/componentes typecheck # tsc --noEmit
pnpm --filter @paquetes/componentes lint # oxlint
pnpm --filter @paquetes/componentes format # oxfmt
pnpm --filter @paquetes/componentes clean # rimraf dist .turboplantilla-react-monorepo/
├── apps/
│ └── webapp/ # Aplicación web principal (Vite 8)
│ ├── src/ # Código fuente React 19
│ ├── entorno/ # Variables de entorno por modo
│ │ ├── .env.desarrollo
│ │ ├── .env.produccion
│ │ └── .env.example
│ ├── index.html # HTML con meta tags de seguridad
│ ├── vite.config.ts # Config Vite 8 + Rolldown + Oxc
│ ├── tailwind.config.js
│ └── tsconfig.json # Extiende @paquetes/configuracion-ts/vite.json
│
├── paquetes/ # Paquetes compartidos (tsdown)
│ ├── api/ # Cliente HTTP (Ky)
│ ├── componentes/ # Componentes React reutilizables
│ ├── configuracion-ts/ # Presets TypeScript
│ │ ├── base.json # Base para todo el monorepo
│ │ ├── vite.json # Para apps (Vite/React)
│ │ └── library.json # Para librerías (tsdown)
│ ├── estados/ # Estado global (Zustand)
│ ├── hooks/ # Hooks personalizados
│ ├── modelos/ # Tipos e interfaces TypeScript
│ └── utiles/ # Funciones helper
│
├── docs/
│ └── CONFIGURACION.md # Guía detallada de configuración
│
├── .github/
│ ├── dependabot.yml # Actualización automática de dependencias
│ └── workflows/ # CI/CD
│
├── .npmrc # ignore-scripts=true (seguridad)
├── .oxlintrc.json # Linter (Rust, 100x más rápido)
├── .oxfmtrc.json # Formatter (Rust, 30x más rápido)
├── turbo.json # Orquestación del monorepo
└── package.json # Dependencias y scripts raíz
| Tecnología | Versión | Rol |
|---|---|---|
| React | 19.x | UI y componentes |
| Vite | 8.x | Bundler + dev server (Rolldown + Oxc nativos) |
| TypeScript | 5.9 | Tipado estático estricto |
| Rolldown | 1.1.x | Bundler Rust (integrado en Vite 8) |
| tsdown | 0.22.x | Empaquetador de librerías (powered by Rolldown) |
| Tailwind CSS | 4.x | Estilos utility-first (motor Oxide) |
| Turborepo | 2.x | Orquestación y caché de monorepo |
| Oxc | 1.71 / 0.56 | Linter (oxlint) + formatter (oxfmt) |
| pnpm | 10.x | Gestión de paquetes con workspaces |
| TanStack Query | 5.x | Data fetching con caché |
| TanStack Table | 8.x | Tablas headless |
| Zustand | 5.x | Estado global minimalista |
| React Router | 7.x | Routing con loaders |
| Ky | 1.x | Cliente HTTP moderno |
| Sonner | 2.x | Notificaciones toast |
| Lucide | 0.563 | Iconos SVG |
Las variables se definen en apps/webapp/entorno/.env.{modo}:
# .env.desarrollo - Para desarrollo local
VITE_API_URL="http://localhost:3000/api"
VITE_DEBUG="true"
VITE_PUERTO="5173"
# .env.produccion - Para builds de producción
VITE_API_URL="https://api.midominio.com"
VITE_DEBUG="false"
VITE_BASE_PATH="/"
⚠️ Importante: Todas las variables deben empezar conVITE_para ser expuestas al cliente. Nunca pongas secretos aquí.
Puedes usar ${VAR} para referenciar otras variables. El sistema resuelve
referencias automáticamente hasta 10 niveles de profundidad:
VITE_PROTOCOL="https"
VITE_HOST="api.midominio.com"
VITE_FULL_URL="${VITE_PROTOCOL}://${VITE_HOST}" # → "https://api.midominio.com"El archivo src/vite-env.d.ts se regenera automáticamente con tipos para
autocompletado en el IDE.
{
build: {
rolldownOptions: {
output: {
minify: { compress: { dropConsole: true, dropDebugger: true } },
},
treeshake: { moduleSideEffects: false, propertyReadSideEffects: false },
codeSplitting: {
nativeGroups: [
{ name: 'react-core', test: /node_modules\/(react|react-dom)\// },
{ name: 'router', test: /node_modules\/react-router-dom\// },
// ...
]
}
}
}
}| Optimización | Beneficio |
|---|---|
| Code splitting por regex | Chunks vendor separados → mejor caché del navegador |
| Tree-shaking agresivo | Eliminación de código muerto más efectiva |
| Minificación con Oxc | 2x más rápido que esbuild, mismo tamaño de bundle |
| CSS con Lightning CSS | Minificación más rápida + syntax lowering moderno |
| Assets con hash | Cache busting perfecto en producción |
| Drop console/debugger | Bundle de producción sin código de debug |
- Pre-bundling con Rolldown: Cold start hasta 10x más rápido que esbuild
- HMR instantáneo: Rolldown procesa cambios en ms
- Chunks lazy: Componentes pesados se cargan bajo demanda
ignore-scripts=true: Ningún paquete puede ejecutar código al instalar- Headers HTTP: X-Content-Type-Options, X-Frame-Options, Referrer-Policy
- HTTPS forzado: HSTS configurado en producción
- FS restrictivo: Vite bloquea acceso a
.env*,*.pem,*.key
Cada paquete en paquetes/* se compila con tsdown
(powered by Rolldown). Ejemplo: paquetes/componentes/tsdown.config.ts:
import { defineConfig } from "tsdown"
export default defineConfig({
entry: ["./src/index.ts"],
format: ["esm"],
platform: "neutral",
dts: true, // Genera y agrupa .d.ts
sourcemap: true,
clean: true,
treeshake: true,
external: ["react", "react-dom", "react/jsx-runtime"],
}){
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": ["dist"],
"sideEffects": false,
"peerDependencies": {
"react": "^19.0.0"
}
}🔑 ¿Por qué
externalpara React? Si empaquetas React dentro de la librería, causa duplicación y rompe los hooks. Marcándolo como external, el consumidor aporta su propia copia.
# 1. Crea la estructura
mkdir paquetes/mi-paquete/src
# 2. Crea el tsdown.config.ts// paquetes/mi-paquete/tsdown.config.ts
import { defineConfig } from "tsdown"
export default defineConfig({
entry: ["./src/index.ts"],
format: ["esm"],
platform: "neutral",
dts: true,
})# 3. Crea el tsconfig.json// paquetes/mi-paquete/tsconfig.json
{
"extends": "../../paquetes/configuracion-ts/library.json",
"include": ["src/**/*.ts", "tsdown.config.ts"]
}# 4. Crea el package.json// paquetes/mi-paquete/package.json
{
"name": "@paquetes/mi-paquete",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": ["dist"],
"sideEffects": false,
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"typecheck": "tsc --noEmit",
"lint": "oxlint src/",
"format": "oxfmt src/",
"clean": "rimraf dist .turbo"
}
}# 5. Crea el código fuente
echo "export const hola = () => 'Hola mundo'" > paquetes/mi-paquete/src/index.ts
# 6. Úsalo en la app
# import { hola } from '@paquetes/mi-paquete'El alias se genera automáticamente desde el nombre en package.json —
no necesitas configurar nada más.
Este proyecto incluye Dependabot configurado para:
- ✅ Revisar dependencias cada lunes a las 9:00 AM
- ✅ Agrupar actualizaciones relacionadas (React, Vite, TanStack, etc.)
- ✅ Automerge de actualizaciones patch y minor (si pasan los tests)
⚠️ Actualizaciones major requieren revisión manual
El automerge está diseñado para ser seguro:
- Solo Dependabot: Verifica que el PR sea realmente de
dependabot[bot] - Tests obligatorios: Solo mergea si pasan typecheck, lint y build
- Sin majors: Las actualizaciones major nunca se auto-mergean
- Auditoría: Cada PR ejecuta
pnpm auditpara detectar vulnerabilidades
Para máxima seguridad, configura estas reglas en GitHub:
Settings → Branches → Add rule → main
☑ Require a pull request before merging
☑ Require status checks to pass before merging
- validate
- build
☑ Require branches to be up to date before merging
☑ Do not allow bypassing the above settings
| Archivo | Propósito |
|---|---|
.github/dependabot.yml |
Configuración de Dependabot |
.github/workflows/ci.yml |
Validación, build y auditoría |
.github/workflows/dependabot-automerge.yml |
Automerge seguro |
- 📖 docs/CONFIGURACION.md: Guía detallada de cada configuración (TypeScript, Vite, Rolldown, tsdown, Turbo, Oxc)
- 🌐 Vite 8 docs
- 🦀 Rolldown
- 📦 tsdown
- ⚡ Oxc
MIT
¡Las contribuciones son bienvenidas! Abre un issue o pull request para sugerencias o mejoras.