Trabajar con React en serio requiere un pequeño ecosistema de herramientas: un entorno de ejecución de JavaScript fuera del navegador (Node.js), un gestor de paquetes (npm), una herramienta de construcción que transforme tu código y te dé un servidor de desarrollo rápido (Vite), un editor bien configurado y una extensión de navegador para inspeccionar componentes. En esta lección montarás ese entorno de principio a fin y crearás el proyecto CicloUrbano que usarás durante todo el curso. Al terminar tendrás una aplicación funcionando en tu navegador y entenderás qué hace cada fichero generado.
Contenido
- Requisitos previos: Node.js y npm
- El editor y sus extensiones
- Crear el proyecto de CicloUrbano con Vite
- Recorrido por la estructura de carpetas
- Los scripts de npm:
dev,build,preview - Recarga en caliente (Hot Module Replacement)
- React DevTools en el navegador
- Por qué Vite y no Create React App
- Requisitos previos: Node.js y npm
React se escribe con una sintaxis (JSX) que los navegadores no entienden directamente y se distribuye en paquetes que hay que descargar. Ambas cosas necesitan Node.js, el entorno que permite ejecutar JavaScript fuera del navegador, y npm (Node Package Manager), que se instala junto con Node.
Qué versión instalar
Usa siempre una versión LTS (Long Term Support): son las versiones pares (20, 22, 24...) con soporte prolongado y las que las herramientas dan por buenas. Vite requiere Node 20.19 o superior. Descárgala de nodejs.org o, mejor aún, instala un gestor de versiones como nvm (macOS/Linux) o fnm (multiplataforma), que te permite tener varias versiones y cambiar entre ellas por proyecto.
Comprobar que todo está en su sitio
Abre una terminal y ejecuta:
Salida esperada (los números concretos variarán, pero el formato es este):
Si el comando no se reconoce, Node no está instalado o no está en el PATH; reinicia la terminal tras instalarlo. Si la versión de Node es inferior a 20, actualízala antes de continuar: verás errores confusos más adelante.
Un apunte sobre gestores de paquetes
| Gestor | Comando de instalación | Notas |
|---|---|---|
| npm | npm install |
Viene con Node. Es el que usaremos en todo el curso |
| pnpm | pnpm install |
Más rápido y ahorra disco al compartir dependencias entre proyectos |
| yarn | yarn |
Alternativa histórica, aún muy usada en proyectos existentes |
Los tres resuelven el mismo problema y los comandos son casi intercambiables. Usaremos npm porque no requiere instalar nada extra.
- El editor y sus extensiones
El editor recomendado es Visual Studio Code, gratuito y con el mejor soporte para React. Estas extensiones aportan una mejora real en el día a día:
| Extensión | Para qué sirve |
|---|---|
| ESLint | Marca errores y malas prácticas mientras escribes (hooks mal usados, variables sin utilizar, key que faltan) |
| Prettier | Formatea el código automáticamente al guardar: se acaban las discusiones sobre comillas e indentación |
| ES7+ React/Redux/React-Native snippets | Atajos como rafce que generan el esqueleto de un componente de función |
| Auto Rename Tag | Al renombrar una etiqueta de apertura en JSX, renombra la de cierre |
| Error Lens | Muestra el mensaje de error en la propia línea, sin tener que pasar el ratón por encima |
Una configuración muy recomendable es activar el formateo al guardar. En VS Code, Ctrl+, → busca «format on save» → márcalo. O directamente en .vscode/settings.json dentro del proyecto:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
- Crear el proyecto de CicloUrbano con Vite
Vite (se pronuncia «vit», rápido en francés) es la herramienta de construcción estándar hoy para proyectos React. Hace dos cosas: durante el desarrollo levanta un servidor casi instantáneo que sirve tu código, y para producción genera los ficheros optimizados que subirás al hosting.
Sitúate en la carpeta donde guardes tus proyectos y ejecuta:
Desmenucemos ese comando, porque los guiones dobles confunden a mucha gente:
npm create vite@latestdescarga y ejecuta el asistente de creación de Vite en su última versión, sin instalarlo permanentemente.ciclourbanoes el nombre de la carpeta del proyecto.- El
--separa los argumentos de npm de los argumentos del asistente. Sin él, npm intentaría interpretar--templatecomo una opción suya. --template reactelige la plantilla de React con JavaScript. (Si quisieras TypeScript seríareact-ts; lo verás en la lección 10-04, pero en este curso usamos JavaScript).
Salida esperada:
Scaffolding project in /home/tu-usuario/proyectos/ciclourbano... Done. Now run: cd ciclourbano npm install npm run dev
Sigue esas tres instrucciones:
npm install lee package.json, descarga las dependencias a la carpeta node_modules/ y crea package-lock.json. Tarda entre unos segundos y un minuto según tu conexión:
Y arranca el servidor de desarrollo:
VITE v7.0.0 ready in 187 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help
Abre http://localhost:5173/ en el navegador: verás la página de bienvenida de Vite + React con un contador. Deja este proceso corriendo en su terminal mientras trabajas; para detenerlo, Ctrl+C.
Si el puerto 5173 está ocupado, Vite usará el 5174, el 5175, etc. Fíjate siempre en la URL que imprime la consola.
- Recorrido por la estructura de carpetas
Esto es lo que Vite ha generado:
ciclourbano/ ├── node_modules/ <- dependencias descargadas (nunca se toca ni se sube a git) ├── public/ <- ficheros estáticos servidos tal cual │ └── vite.svg ├── src/ <- TU código: aquí trabajarás siempre │ ├── assets/ │ │ └── react.svg │ ├── App.css │ ├── App.jsx <- componente raíz de la aplicación │ ├── index.css <- estilos globales │ └── main.jsx <- punto de entrada de JavaScript ├── .gitignore ├── eslint.config.js ├── index.html <- página HTML real que sirve el navegador ├── package.json ├── package-lock.json ├── README.md └── vite.config.js
index.html: el punto de partida real
En un proyecto Vite, el HTML no está escondido dentro de la configuración: es un fichero de primer nivel y es el verdadero punto de entrada.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>Dos líneas son las importantes:
<div id="root"></div>es el contenedor vacío donde React montará toda la aplicación. Todo lo que verás en pantalla acabará dentro de esediv.<script type="module" src="/src/main.jsx">carga tu código como módulo ES. Es el hilo que enlaza el HTML con React.
Aprovecha para personalizarlo ahora, ya que es tu proyecto:
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CicloUrbano — Alquiler de bicicletas urbanas</title>
</head>src/main.jsx: donde arranca React
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
);Es el fichero que conecta React con el div#root del HTML. Lo analizaremos línea a línea en la siguiente lección; por ahora quédate con que aquí empieza todo.
El resto de piezas
| Fichero / carpeta | Para qué sirve |
|---|---|
src/App.jsx |
Componente raíz. De él cuelga el árbol completo de componentes de CicloUrbano |
src/index.css |
Estilos globales: tipografía base, colores, reinicio de márgenes |
src/App.css |
Estilos del componente App (en el Módulo 2 verás mejores estrategias) |
src/assets/ |
Imágenes y recursos que importas desde el código; Vite los optimiza y les añade un hash al construir |
public/ |
Recursos servidos tal cual, sin procesar, en la raíz del sitio: public/logo.png se sirve como /logo.png. Úsala para favicon.ico, robots.txt o descargas |
package.json |
Nombre del proyecto, dependencias y scripts ejecutables |
package-lock.json |
Versiones exactas instaladas. Se sube a git para que todo el equipo instale lo mismo |
vite.config.js |
Configuración de Vite (plugins, alias, puerto, proxy) |
eslint.config.js |
Reglas de análisis estático del código |
.gitignore |
Lista de lo que git debe ignorar; incluye node_modules/ y dist/ |
node_modules/ |
Dependencias descargadas. Pesa mucho, se regenera con npm install y nunca se sube a git |
Diferencia clave entre src/assets/ y public/: lo que está en assets pasa por el proceso de construcción (se optimiza, se renombra con un hash para cachear bien y, si no se usa, se elimina); lo que está en public se copia sin tocar y su nombre no cambia.
vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()]
});Es mínimo a propósito. El plugin @vitejs/plugin-react es el que enseña a Vite a transformar JSX y el que habilita la recarga en caliente de componentes. Si más adelante necesitas un alias de rutas o un proxy hacia una API, se configura aquí.
Cómo encajan las piezas
flowchart TD
A[Navegador pide index.html] --> B["index.html contiene div#root<br/>y carga /src/main.jsx"]
B --> C[main.jsx: createRoot + render]
C --> D[App.jsx: componente raíz]
D --> E[Componentes de CicloUrbano<br/>src/componentes/]
F[Vite: servidor de desarrollo] -.transforma JSX al vuelo.-> B
- Los scripts de npm:
dev, build, preview
dev, build, previewÁbrelo tú mismo, package.json:
{
"name": "ciclourbano",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.4.0",
"eslint": "^9.25.0",
"vite": "^7.0.0"
}
}| Script | Comando | Qué hace | Cuándo lo usas |
|---|---|---|---|
dev |
npm run dev |
Levanta el servidor de desarrollo con recarga en caliente en localhost:5173 |
Todo el rato mientras programas |
build |
npm run build |
Genera la versión de producción optimizada en dist/ |
Antes de desplegar |
preview |
npm run preview |
Sirve localmente lo que hay en dist/ para comprobarlo |
Después de build, para validar antes de subir |
lint |
npm run lint |
Analiza el código en busca de errores y malas prácticas | Antes de confirmar cambios en git |
Prueba el ciclo completo ahora:
vite v7.0.0 building for production... ✓ 34 modules transformed. dist/index.html 0.46 kB │ gzip: 0.30 kB dist/assets/index-DiwrgTda.css 1.39 kB │ gzip: 0.72 kB dist/assets/index-C9n2Xk4p.js 143.41 kB │ gzip: 46.12 kB ✓ built in 612 ms
Observa dos detalles importantes: preview usa un puerto distinto (4173) para que no lo confundas con el de desarrollo, y los ficheros de dist/ llevan un hash en el nombre (index-C9n2Xk4p.js). Ese hash cambia cuando cambia el contenido, lo que permite al navegador cachear agresivamente sin servir nunca una versión antigua.
Sobre dependencies frente a devDependencies: las primeras acaban en el paquete que llega al navegador (react, react-dom); las segundas solo se usan en tu máquina para construir y analizar el código (vite, eslint). Por eso el resultado de build pesa mucho menos que node_modules/.
- Recarga en caliente (Hot Module Replacement)
El HMR (Hot Module Replacement, sustitución de módulos en caliente) es la razón por la que el desarrollo con Vite resulta tan cómodo. Cuando guardas un fichero, Vite no recarga la página entera: envía por WebSocket solo el módulo que ha cambiado y React lo sustituye en vivo.
La diferencia práctica es enorme:
| Recarga completa | HMR | |
|---|---|---|
| Tiempo hasta ver el cambio | 1-3 segundos | Decenas de milisegundos |
| Estado de la aplicación | Se pierde: vuelves al inicio | Se conserva |
| Scroll y foco | Se reinician | Se mantienen |
El «estado se conserva» es lo que más agradecerás: si has rellenado medio formulario de reserva de CicloUrbano y ajustas un color en el CSS, sigues viendo el formulario relleno.
Pruébalo. Con npm run dev corriendo, abre src/App.jsx, cambia cualquier texto visible y guarda. El navegador se actualiza solo, sin parpadeo. En la consola de Vite verás:
Hay casos en que el HMR no puede aplicar el cambio y recarga la página entera: al modificar vite.config.js, al tocar index.html, o cuando cambias la estructura de un módulo de forma que Vite no puede reconciliar. Es normal.
- React DevTools en el navegador
React DevTools es la extensión oficial que permite inspeccionar tu aplicación en términos de React —componentes, props, estado— en lugar de en términos de nodos HTML.
Instalación
- Chrome / Edge: busca «React Developer Tools» en Chrome Web Store e instálala.
- Firefox: búscala en addons.mozilla.org.
- Safari u otros: se puede usar la versión independiente con
npx react-devtools.
Tras instalarla, abre http://localhost:5173, pulsa F12 y verás dos pestañas nuevas: Components y Profiler.
Qué muestra la pestaña Components
- El árbol de componentes con sus nombres reales (
App,ListaBicicletas,TarjetaBicicleta), en vez de una maraña dediv. Esta es la razón principal para instalarla. - Props y estado del componente seleccionado, en el panel derecho, y editables al vuelo para probar casos sin tocar el código.
- El componente padre que lo renderiza y la ruta completa hasta la raíz.
- Un selector (icono de flecha) para pinchar un elemento de la página y saltar a su componente.
Comprueba que funciona: abre Components y verás App en el árbol, y dentro de él StrictMode. Todavía hay poco que ver, pero a partir de la lección 01-03 esta pestaña será tu herramienta de diagnóstico principal.
La pestaña Profiler mide el rendimiento de los renders. Es una herramienta excelente, pero requiere entender antes cómo renderiza React; se estudia en la lección Medir el Rendimiento con React DevTools Profiler.
- Por qué Vite y no Create React App
Durante años, la forma estándar de crear un proyecto React fue create-react-app (CRA). Hoy no debes usarlo:
- Está descontinuado. La documentación oficial de React lo retiró de sus recomendaciones en 2023 y el paquete dejó de mantenerse activamente. Instalarlo hoy muestra avisos de dependencias obsoletas.
- Es lento. CRA usa webpack con Babel y empaqueta toda la aplicación antes de poder servir nada: arrancar un proyecto mediano podía llevar 30 segundos o más, y cada cambio varios segundos. Vite sirve los módulos ES nativamente y usa esbuild (escrito en Go) para las dependencias: arranca en menos de un segundo con independencia del tamaño del proyecto.
- Es opaco. Su configuración está escondida tras
react-scripts, y personalizarla obligaba aeject(una operación irreversible que vuelca cientos de líneas de configuración en tu repositorio) o a parches externos.vite.config.jsson cinco líneas legibles.
| Create React App | Vite | |
|---|---|---|
| Estado | Descontinuado | Activo y estándar de facto |
| Arranque del servidor | Decenas de segundos | Menos de un segundo |
| Actualización tras un cambio | Segundos | Milisegundos |
| Configuración | Oculta; eject irreversible |
Fichero corto y editable |
| Construcción de producción | webpack | Rollup, con división de código incluida |
Que CRA aparezca en tutoriales antiguos es la mejor señal para desconfiar de su actualidad: si un tutorial usa create-react-app, probablemente también use componentes de clase y APIs anteriores a los hooks. Menciónalo solo como contexto histórico.
Errores Comunes y Consejos
- Ejecutar
npm run devfuera de la carpeta del proyecto. Danpm error Missing script: "dev". Comprueba conpwd(ols package.json) que estás dentro deciclourbano/. - Olvidar el
--en el comando de creación.npm create vite@latest ciclourbano --template reactno pasa la plantilla al asistente y este te preguntará interactivamente. No es un error grave, pero conviene saber por qué ocurre. - Subir
node_modules/a git. Son decenas de miles de ficheros. El.gitignoreque genera Vite ya lo excluye; no lo borres. Si alguien clona el repositorio, connpm installlo reconstruye. - Editar ficheros dentro de
node_modules/. Cualquier cambio ahí desaparecerá en la siguiente instalación. Si necesitas modificar una dependencia, existen herramientas específicas (patch-package), pero casi nunca es la solución correcta. - Node en una versión demasiado antigua. Es la causa número uno de errores incomprensibles al instalar o arrancar. Verifica siempre
node --versionantes de pedir ayuda. - Cerrar la terminal donde corre
npm run devy esperar que la web siga funcionando. El servidor de desarrollo es ese proceso; si lo matas,localhost:5173deja de responder. - Confundir el puerto de
devcon el depreview. 5173 sirve tu código en desarrollo, 4173 sirve el contenido dedist/. Si editas y no ves cambios, comprueba en qué puerto estás. - Consejo: añade el proyecto a git desde el primer día (
git init,git add .,git commit -m "Proyecto inicial de CicloUrbano"). Poder volver a un punto que funcionaba vale oro mientras aprendes.
Ejercicios
Ejercicio 1
Crea el proyecto de CicloUrbano siguiendo los pasos de la lección y, a continuación:
- Cambia el
<title>deindex.htmlaCicloUrbano — Alquiler de bicicletas urbanasy el atributolangaes. - Con el servidor de desarrollo en marcha, modifica cualquier texto de
src/App.jsxy comprueba que el cambio aparece sin recargar la página. - Ejecuta la construcción de producción y sírvela localmente. Anota qué puerto usa y qué tamaño tiene el fichero JavaScript generado.
Ejercicio 2
Clasifica cada uno de estos ficheros o carpetas en una de tres categorías: (A) lo edito habitualmente, (B) existe pero casi nunca lo toco, (C) nunca lo edito a mano.
src/App.jsx · node_modules/ · package.json · package-lock.json · index.html · vite.config.js · src/componentes/ · dist/
Ejercicio 3
Coloca dos imágenes en el proyecto: logo-ciclourbano.svg en public/ y bicicleta-urbana.svg en src/assets/. Explica con qué ruta referenciarías cada una y qué le pasa a cada fichero al ejecutar npm run build.
Soluciones
Solución 1.
Edita index.html:
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CicloUrbano — Alquiler de bicicletas urbanas</title>
</head>Al guardar src/App.jsx con un texto distinto, el navegador se actualiza en milisegundos sin perder el estado (si habías pulsado el contador de ejemplo, mantiene su valor): eso es el HMR en acción. La consola de Vite imprime [vite] hmr update /src/App.jsx.
Para el tercer punto:
preview sirve en http://localhost:4173/. El fichero JavaScript rondará los 140-150 kB (unos 45 kB comprimidos con gzip), que es esencialmente el peso de React y React DOM.
Solución 2.
| Fichero / carpeta | Categoría | Motivo |
|---|---|---|
src/App.jsx |
A | Es tu componente raíz; lo tocas constantemente |
src/componentes/ |
A | Aquí vivirán todos los componentes de CicloUrbano |
package.json |
B | Se modifica al añadir scripts; las dependencias las gestiona npm install |
index.html |
B | Título, idioma, favicon y metadatos; después casi no se toca |
vite.config.js |
B | Solo cuando necesites un alias, un proxy o un plugin |
node_modules/ |
C | Generada por npm; cualquier cambio se pierde |
package-lock.json |
C | Lo gestiona npm; se confirma en git pero no se edita a mano |
dist/ |
C | Salida de npm run build; se regenera y ni siquiera se sube a git |
Solución 3.
-
public/logo-ciclourbano.svgse sirve tal cual desde la raíz del sitio. Se referencia con una ruta absoluta y su nombre no cambia nunca:<img src="/logo-ciclourbano.svg" alt="CicloUrbano" />Tras
npm run buildaparece endist/logo-ciclourbano.svgcon el mismo nombre. Es la opción correcta cuando la ruta debe ser estable y predecible (favicon,robots.txt, imágenes referenciadas desde fuera). -
src/assets/bicicleta-urbana.svgse importa desde el código:import bicicletaUrbana from './assets/bicicleta-urbana.svg'; <img src={bicicletaUrbana} alt="Bicicleta urbana" />Al construir, Vite lo procesa, lo renombra con un hash (
dist/assets/bicicleta-urbana-B7kX2p1q.svg) y sustituye la referencia. Ventajas: caché óptima en el navegador, error en tiempo de construcción si la ruta está mal escrita, y eliminación automática si el fichero deja de usarse.
Conclusión
Ya tienes un entorno de desarrollo profesional: Node.js LTS y npm verificados, un editor con ESLint y Prettier, el proyecto CicloUrbano creado con Vite, el servidor de desarrollo corriendo con recarga en caliente y React DevTools instalado en el navegador. También sabes qué hace cada fichero generado, en qué se diferencian src/assets/ y public/, para qué sirve cada script de npm y por qué Vite ha sustituido a Create React App.
Hasta ahora solo has ejecutado código ajeno. En la siguiente lección, Hola Mundo en React, limpiarás la plantilla de ejemplo, entenderás línea a línea cómo main.jsx monta la aplicación en el DOM y escribirás tus dos primeros componentes propios: Bienvenida y TarjetaBicicleta.
Curso de React
Módulo 1: Introducción a React
- ¿Qué es React?
- Configuración del Entorno de Desarrollo
- Hola Mundo en React
- JSX: Extensión de Sintaxis de JavaScript
- Cómo Renderiza React: Virtual DOM y Reconciliación
Módulo 2: Componentes de React
- Entendiendo los Componentes
- Componentes Funcionales vs de Clase
- Props: Pasando Datos a Componentes
- State: Gestión del Estado del Componente
- Estilos en los Componentes: CSS, Módulos y Utilidades
Módulo 3: Trabajando con Eventos
- Manejo de Eventos en React
- Renderizado Condicional
- Listas y Claves
- Formularios y Componentes Controlados
- Validación de Formularios y Componentes No Controlados
- Accesibilidad en Componentes Interactivos
Módulo 4: Conceptos Avanzados de Componentes
- Elevando el Estado
- Composición vs Herencia
- Métodos del Ciclo de Vida de React
- Hooks: Introducción y Uso Básico
- Límites de Error: Capturar Fallos en la Interfaz
Módulo 5: Hooks de React
- Hook useState
- Hook useEffect
- Hook useRef y Acceso al DOM
- Hook useContext
- Hook useReducer
- Hooks Personalizados
Módulo 6: Enrutamiento en React
- Introducción a React Router
- Configuración de React Router
- Rutas Anidadas
- Navegación Programática
- Rutas Protegidas y Control de Acceso
Módulo 7: Gestión del Estado
- Introducción a la Gestión del Estado
- API de Contexto
- Redux: Introducción y Configuración
- Redux: Acciones y Reductores
- Redux: Conectando a React
- Estado del Servidor: Peticiones, Caché y Sincronización
Módulo 8: Optimización del Rendimiento
- Técnicas de Optimización del Rendimiento en React
- Memorización con React.memo
- Hooks useMemo y useCallback
- División de Código y Carga Perezosa
- Medir el Rendimiento con React DevTools Profiler
Módulo 9: Pruebas en React
- Introducción a las Pruebas
- Pruebas Unitarias con Jest
- Pruebas de Componentes con React Testing Library
- Pruebas de Código Asíncrono y Simulación de APIs
- Pruebas de Extremo a Extremo con Cypress
Módulo 10: Temas Avanzados
- Renderizado del Lado del Servidor (SSR) con Next.js
- Generación de Sitios Estáticos (SSG) con Next.js
- Suspense y React Server Components
- TypeScript con React
- React Native: Creación de Aplicaciones Móviles
