Skip to content
This page has been auto-translated and may contain errors.View in English

Configurar un proyecto de React

Una app de React necesita un poco de herramientas alrededor antes de que cualquier código se ejecute. Algo tiene que convertir JSX en JavaScript que el navegador pueda ejecutar, y algo tiene que servir el resultado mientras trabajas en él. Vite hace ambas cosas, y genera un proyecto funcional en unos treinta segundos. Este capítulo va desde una carpeta vacía hasta una app en funcionamiento, y luego rastrea el camino que más importa: cómo un componente termina en la pantalla.

Crear un proyecto

Vite es una herramienta de compilación con un generador de proyectos integrado. Ejecútalo con npm create, responde dos preguntas, y tienes un proyecto:

bash
npm create vite@latest mi-app-react
cd mi-app-react
npm install
npm run dev

El primer comando te pregunta qué framework quieres (elige React) y qué variante (elige JavaScript, o TypeScript si lo estás usando). Escribe una carpeta llamada mi-app-react con todo lo que un proyecto de React necesita. npm install descarga las dependencias listadas en package.json, que es de donde viene React. npm run dev inicia el servidor de desarrollo e imprime una dirección local, generalmente http://localhost:5173. Abre eso en un navegador y la app inicial está en funcionamiento.

La carpeta generada tiene algunos archivos que importan al principio:

  • index.html: la página HTML única que el navegador carga.
  • src/main.jsx: el punto de entrada, donde React se conecta a esa página.
  • src/App.jsx: tu componente de nivel superior, y el archivo que editarás primero.
  • src/assets/: imágenes y otros archivos estáticos que importas en componentes.
  • package.json: dependencias y los scripts dev, build, y preview.
  • vite.config.js: configuración de compilación, que puedes dejar sin tocar durante mucho tiempo.

Cómo se conectan las piezas

Tres archivos se pasan uno al otro en línea recta. Comienza en index.html, que es deliberadamente casi vacío:

html
<body>
  <div id="root"></div>
  <!-- seguido de una etiqueta <script type="module" src="/src/main.jsx"> -->
</body>

Ese <div id="root"> vacío es el lugar en la página que React puede llenar. Todo lo que tu app renderiza se pone dentro de él. La etiqueta de módulo <script> debajo carga main.jsx, que es donde React toma el control:

jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>
)

Lee esa llamada de derecha a izquierda. document.getElementById('root') encuentra el div vacío. createRoot lo envuelve en una raíz de React, lo que significa que React ahora es dueño del contenido de ese elemento y lo mantendrá sincronizado con tus componentes. .render(...) le dice qué poner ahí: el componente App.

<StrictMode> es un envoltorio solo para desarrollo que ejecuta verificaciones adicionales en todo lo que hay dentro y advierte sobre patrones que probablemente causen bugs. No agrega nada a la página y se desactiva a sí mismo en una compilación de producción. Su efecto más visible aparece en Effects, donde deliberadamente monta cada componente dos veces durante el desarrollo.

App.jsx es un componente ordinario que se exporta a sí mismo:

jsx
export default function App() {
  return <h1>Hola desde React</h1>
}

Esa es toda la cadena. El navegador carga index.html, el script carga main.jsx, main.jsx llama a createRoot en el div raíz y renderiza <App />, y App devuelve el JSX que se convierte en el encabezado que ves. Cada componente que escribas de aquí en adelante se sienta en algún lugar dentro de App, así que llega a la página por este mismo camino. main.jsx generalmente se escribe una vez y rara vez se toca nuevamente; casi todo tu trabajo sucede en App.jsx y los componentes que trae consigo.

Nota de versión

React 17 y anteriores usaban ReactDOM.render(<App />, document.getElementById('root')) como punto de entrada. React 18 introdujo createRoot, que es lo que activa el renderizado concurrente, y dejó la llamada anterior funcionando con una advertencia de deprecación. React 19 la eliminó, así que ReactDOM.render ahora lanza un error. En un tutorial que todavía la use, createRoot es la línea que debes escribir en su lugar. Mira History and versions para ver qué cambió.

El servidor de desarrollo

npm run dev inicia el servidor de desarrollo de Vite, y se mantiene ejecutándose en la terminal mientras trabajas. Su trabajo es servir tu app y reaccionar a tus ediciones.

Guarda un cambio en App.jsx y el navegador se actualiza casi inmediatamente, sin una recarga manual. Eso es reemplazo de módulo en caliente: Vite envía el módulo modificado a la página y lo intercambia, dejando el resto de la app en funcionamiento. Un contador que hubieras hecho clic hasta siete generalmente sigue mostrando siete después de la edición, así que mantienes cualquier estado que hayas establecido mientras ajustas el marcado alrededor. Algunos cambios aún fuerzan una recarga completa, y Vite lo decide por ti.

Dos scripts más vienen con el proyecto. npm run build produce un bundle optimizado en una carpeta dist, que es lo que despliegas. npm run preview sirve ese resultado compilado localmente para que puedas verificarlo antes de enviarlo. Durante el desarrollo, npm run dev es el único que necesitas.

Importar activos estáticos

Las imágenes viven bajo src/assets y entran en un componente a través de un import:

jsx
import logo from './assets/logo.png'

export default function Header() {
  return <img src={logo} alt="Logo de la empresa" />
}

El import te da una variable que contiene la URL final de esa imagen, que luego pasas a src entre llaves. Escribir src="./assets/logo.png" como una cadena simple tiende a romperse, porque las rutas en tu carpeta de origen raramente son las rutas en el resultado compilado.

Importar el archivo en su lugar pone la herramienta de compilación en el ciclo. Ve que tu código depende de logo.png, lo copia en el resultado, y te devuelve cualquier URL en la que termine ese archivo. Mueve tu componente a una carpeta diferente y el import relativo aún se resuelve. Escribe mal el nombre de archivo y te das cuenta inmediatamente, porque el import falla, en lugar de descubrir una imagen rota en producción. El mismo patrón funciona para SVGs, fuentes, y cualquier otro archivo que la herramienta de compilación sepa manejar.

Un navegador no tiene idea de qué es un archivo .jsx. No hay un parser de JSX en ningún motor de JavaScript, y <App /> es un error de sintaxis en JavaScript plano. Lo que el navegador recibe ya ha sido transformado. Vite ejecuta cada archivo .jsx a través de esbuild, que reescribe el JSX en llamadas a funciones: bajo el tiempo de ejecución automático de React 19, <App /> se convierte en una llamada como _jsx(App, {}). Qué helper obtienes depende del modo. La transformación de producción importa jsx desde react/jsx-runtime, mientras que la transformación de desarrollo importa jsxDEV desde react/jsx-dev-runtime y pasa argumentos adicionales que llevan el archivo fuente y el número de línea, que es cómo una advertencia de React en tu consola puede apuntar exactamente a dónde está en tu código. La extensión .jsx es principalmente una señal a las herramientas de que este archivo contiene sintaxis que necesita esa transformación. Para cuando algo llega a la página, son módulos JavaScript ordinarios llamando a funciones ordinarias.

El servidor de desarrollo y la compilación de producción toman rutas diferentes hacia ese resultado. En desarrollo, Vite sirve módulos ES nativos y transforma cada archivo bajo demanda, así que el tiempo de inicio apenas crece con el tamaño del proyecto y una única edición solo invalida ese módulo. npm run build cambia a Rollup, que agrupa todo el gráfico, quita exportaciones no utilizadas, minifica, y divide el código en chunks. El comportamiento puede diferir ligeramente entre los dos, que es por qué npm run preview existe.

El import de imagen funciona porque el bundler también trata archivos que no son JavaScript como parte del gráfico de módulos. import logo from './assets/logo.png' no es un import de módulo de JavaScript real. Vite lo intercepta, emite el archivo en dist/assets con un hash de contenido en el nombre, y reemplaza el import con un literal de string de esa ruta final, algo como /assets/logo-4f2a1c8b.png. El hash es lo que hace seguro el caching agresivo: cambia la imagen y el nombre de archivo cambia con ella, así que ninguna copia obsoleta sobrevive en un CDN. Los archivos por debajo de un umbral de tamaño (4KB por defecto) omiten la solicitud separada completamente y se incrustan como una URL de datos base64. En desarrollo el mismo import se resuelve en una ruta simple servida por el servidor de desarrollo, que es por qué la URL que ves en devtools difiere entre npm run dev y una compilación real.

JunoUn camino desde la página a tu componente La configuración son cuatro comandos, y luego puedes olvidarte de ella. Lo que vale la pena recordar es la cadena: index.html tiene un div vacío con la id root, main.jsx atrapa ese div con createRoot y renderiza <App /> en él, y App.jsx es el componente que dice qué aparece. Una vez que puedas seguir ese camino, sabes exactamente dónde se conecta tu propio código.
JunoUn camino desde la página a tu componentenpm create vite@latest, elige React, instala, npm run dev. De ahí es index.html a main.jsx a App.jsx: el archivo de entrada llama a createRoot en el div raíz una vez y renderiza tu componente superior, y pasas el resto de tu tiempo debajo de esa línea. Importa imágenes en lugar de codificar rutas para que la herramienta de compilación las resuelva y les agregue huella digital.
JunoUn camino desde la página a tu componente La configuración existe porque JSX no tiene tiempo de ejecución: esbuild reescribe <App /> en llamadas de tiempo de ejecución, jsx desde react/jsx-runtime en una compilación y jsxDEV desde react/jsx-dev-runtime en desarrollo, antes de que algo llegue al navegador, e los imports de activos se resuelven en URLs con hash que el bundler emite. Dev ejecuta módulos ES no agrupados a través de esbuild, producción ejecuta Rollup, así que trata npm run preview como la verificación de que los dos estén de acuerdo. createRoot es el punto de entrada de React 18, y es lo que abre tu árbol al renderizado concurrente.

Lo siguiente: Components, los bloques de construcción con los que llenarás ese App.jsx.