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

Configurar un proyecto de React

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

Crear un proyecto

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

bash
npm create vite@latest my-react-app
cd my-react-app
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). Crea una carpeta llamada my-react-app con todo lo que necesita un proyecto de React. 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, normalmente http://localhost:5173. Abre esa dirección en un navegador y la aplicación inicial está ejecutándose.

La carpeta generada tiene varios archivos que importan desde el principio:

  • index.html: la única página HTML que carga el navegador.
  • src/main.jsx: el punto de entrada, donde React se vincula 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 construcción, que puedes dejar como está durante mucho tiempo.

Cómo se conectan las piezas

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

html
<body>
  <div id="root"></div>
  <!-- followed by a <script type="module" src="/src/main.jsx"> tag -->
</body>

Ese <div id="root"> vacío es el lugar en la página donde React puede escribir. Todo lo que renderiza tu aplicación termina dentro de él. La etiqueta <script> del módulo 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 mantiene sincronizado con tus componentes. .render(...) le dice qué poner allí: el componente App.

<StrictMode> es un envoltorio solo para desarrollo que ejecuta controles adicionales en todo lo que hay dentro y advierte sobre patrones que probablemente causen errores. No agrega nada a la página y se desactiva a sí mismo en una construcció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>Hello from 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 encuentra en algún lugar dentro de App, así que llega a la página a través de este mismo camino. main.jsx generalmente se escribe una sola vez y rara vez se toca nuevamente; casi todo tu trabajo sucede en App.jsx y los componentes que importa.

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 antigua funcionando con una advertencia de deprecación. React 19 la removió, así que ReactDOM.render ahora lanza un error. En un tutorial que todavía la usa, createRoot es la línea que debes escribir en su lugar. Consulta History and versions para ver qué cambió.

El servidor de desarrollo

npm run dev inicia el servidor de desarrollo de Vite, y continúa ejecutándose en la terminal mientras trabajas. Su trabajo es servir tu aplicación y reaccionar a tus cambios.

Guarda un cambio en App.jsx y el navegador se actualiza casi inmediatamente, sin una actualización manual. Eso es reemplazo de módulo en caliente: Vite envía el módulo modificado a la página y lo intercambia en su lugar, dejando el resto de la aplicación funcionando. Un contador que hubieras hecho clic hasta llegar al siete generalmente sigue leyendo siete después del cambio, así que conservas el estado que habías configurado mientras ajustas el marcado alrededor. Algunos cambios aún fuerzan una recarga completa, y Vite lo decide por ti.

Otros dos scripts vienen con el proyecto. npm run build produce un bundle optimizado en una carpeta dist, que es lo que despliegas. npm run preview sirve esa salida compilada localmente para que puedas verificarla antes de enviarla. Durante el desarrollo, npm run dev es el único que necesitas.

Importar recursos 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="Company logo" />
}

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 plana tiende a romperse, porque las rutas en tu carpeta fuente rara vez son las rutas en la salida compilada.

Importar el archivo en su lugar pone la herramienta de construcción en el ciclo. Ve que tu código depende de logo.png, lo copia a la salida, y te devuelve cualquier URL en la que ese archivo termine. Mueve tu componente a una carpeta diferente y el import relativo se resuelve igual. Escribe mal el nombre del archivo y te enteras 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 construcción sepa cómo manejar.

Un navegador no tiene idea de qué es un archivo .jsx. No hay analizador JSX en ningún motor de JavaScript, y <App /> es un error de sintaxis en JavaScript plano. Lo que recibe el navegador ya ha sido transformado. Vite ejecuta cada archivo .jsx a través de esbuild, que reescribe el JSX en llamadas de función: 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 de react/jsx-runtime, mientras que la transformación de desarrollo importa jsxDEV de react/jsx-dev-runtime y pasa argumentos adicionales que contienen el archivo fuente y el número de línea, que es cómo una advertencia de React en tu consola puede señalar el lugar exacto 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 que llaman a funciones ordinarias.

El servidor de desarrollo y la construcción de producción toman rutas diferentes para llegar a 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 un único cambio solo invalida ese módulo. npm run build cambia a Rollup, que agrupa el gráfico completo, realiza tree-shake de 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 imágenes 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 cadena de esa ruta final, algo como /assets/logo-4f2a1c8b.png. El hash es lo que hace seguro el almacenamiento en caché agresivo: cambia la imagen y el nombre de archivo cambia con ella, así que ninguna copia antigua 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 a una ruta plana servida por el servidor de desarrollo, que es por qué la URL que ves en devtools difiere entre npm run dev y una construcción real.

JunoUn camino desde la página hasta tu componente La configuración son cuatro comandos, y luego puedes olvidarte de ella.

Lo que vale la pena retener es la cadena: index.html tiene un div vacío con el id root, main.jsx agarra ese div con createRoot y renderiza <App /> dentro de é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 código.

JunoUn camino desde la página hasta 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 sola 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 construcción las resuelva y las marque con huella digital para ti.

JunoUn camino desde la página hasta 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 de react/jsx-runtime en una construcción y jsxDEV de react/jsx-dev-runtime en desarrollo, antes de que nada llegue al navegador, e importaciones de recursos se resuelven a URLs con hash que emite el bundler.

Dev ejecuta módulos ES sin agrupar 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 permite el renderizado concurrente en tu árbol.

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