React desde Cero: Crea tu App y Empaquétala en un Solo Archivo index.js
Del entorno local a un solo bundle: el arte de combinar React en un archivo autosuficiente.
Por HolaGPT Editorial · 10 min lectura · 2026-07-09
La mayoría de los proyectos React se crean con herramientas como Create React App, que generan una estructura de carpetas y un proceso de compilación que produce múltiples archivos JavaScript, CSS y assets. Pero ¿qué ocurre cuando necesitas distribuir tu aplicación como un único archivo, un archivo index.js autónomo que se puede cargar con una simple etiqueta script? Esta necesidad surge en contextos como la creación de widgets embebibles, extensiones de navegador o componentes para plataformas que exigen un solo punto de entrada.
Como desarrollador frontend con experiencia en React, he ayudado a numerosos equipos a compactar sus proyectos en un bundle único. En este artículo te guío para que construyas tu propia aplicación desde cero y la conviertas en un solo archivo listo para producción. No importa si partes de cero o ya tienes un proyecto, verás las técnicas y configuraciones necesarias para lograrlo.
Vamos a sumergirnos en el código con ejemplos reales. Antes de continuar, te pregunto: ¿cuál es el caso de uso concreto que buscas? Saber si es un widget, una SPA offline o una integración nos permitirá ajustar la estrategia de bundling.
¿Por qué empaquetar en un único archivo?
El ecosistema de React suele fragmentar las aplicaciones en decenas de chunks para mejorar la carga diferida y aprovechar el almacenamiento en caché. Sin embargo, ciertos escenarios exigen lo contrario: un solo archivo que contenga toda la lógica, los componentes, los estilos y los recursos. Cuando incrustas un widget en un sitio de terceros, por ejemplo, no puedes asumir que habrá un gestor de módulos ni un paso de compilación. Un único script facilita la integración y evita incompatibilidades.
Además, la portabilidad es extrema: pruebas el archivo en cualquier entorno con un doble clic, lo alojas en un CDN sin servidor que sirva múltiples assets, o lo empaquetas en una extensión de Chrome sin preocuparte por rutas relativas. Incluso para prototipos rápidos, un solo bundle reduce la sobrecarga de configuración.
Herramientas que necesitarás
Para construir la aplicación desde cero y unificar su salida, necesitarás Node.js y npm (o yarn). Como bundler, utilizaré dos enfoques: Vite, por su velocidad y simplicidad, y Webpack, para quienes requieran hasta el último detalle de personalización. Ambos te permiten producir un solo archivo JavaScript que funcione de inmediato en cualquier navegador moderno.
Creando el proyecto con Vite
Abre tu terminal y ejecuta el comando para crear un proyecto React con la plantilla oficial de Vite:
npm create vite@latest mi-app -- --template reactAccede a la carpeta, instala las dependencias con npm install y ejecuta npm run dev para verificar que la app funciona. Ahora tendrás la estructura típica con src/main.jsx como punto de entrada. Modifica el index.html para que solo tenga un <div id='root'></div>, porque nuestro bundle lo inyectará todo vía JavaScript.
Configurando la salida a un solo archivo
El corazón de la transformación está en vite.config.js. Con la API de librería de Vite, indicamos la entrada, el nombre de la función global y el formato IIFE (expresión de función invocada inmediatamente) para aislar el código. La clave está en rollupOptions y inlineDynamicImports: true, que obliga a Rollup a meter todo en un mismo archivo.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
lib: {
entry: 'src/main.jsx',
name: 'MiApp',
formats: ['iife'],
fileName: () => 'index.js'
},
rollupOptions: {
output: {
inlineDynamicImports: true
}
},
cssCodeSplit: false
}
});El parámetro cssCodeSplit: false impide que Vite genere archivos CSS separados. Para que los estilos se incrusten dentro del bundle, necesitas un plugin adicional o importar los archivos de estilo con una sintaxis especial. Una opción limpia es usar vite-plugin-css-injected-by-js: instálalo y añádelo al array de plugins. Otra vía, si trabajas con CSS modules, es importar el CSS con el sufijo ?inline e inyectarlo manualmente en el DOM.
Cuando ejecutes npm run build, obtendrás un único dist/index.js autosuficiente. Incluye React, ReactDOM y todo tu código de componentes.
Armando un bundle con Webpack desde cero
Si prefieres un control absoluto, Webpack sigue siendo una opción robusta. Comienza instalando las dependencias necesarias:
npm install --save-dev webpack webpack-cli babel-loader @babel/core @babel/preset-env @babel/preset-react style-loader css-loader url-loaderCrea un archivo webpack.config.js con la siguiente configuración:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
library: {
type: 'umd',
name: 'MiApp'
},
globalObject: 'this'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jpg|gif|svg)$/,
use: {
loader: 'url-loader',
options: {
limit: Infinity // todo se convierte a base64
}
}
}
]
},
resolve: {
extensions: ['.js', '.jsx']
}
};El punto de entrada src/index.js debe montar el componente React en el DOM. Un ejemplo típico:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './styles.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( );Con el comando npx webpack --mode production generarás un solo dist/index.js que incluye React, tu aplicación, el CSS y las imágenes en base64.
Manejando estilos y assets
En ambos setups, el manejo de estilos influye en la completitud del bundle. Con style-loader (en Webpack) o el plugin de inyección de Vite, el CSS se inserta dinámicamente cuando el script se carga, sin generar archivos extra. Para imágenes y fuentes, la opción más sencilla es incrustarlas como data URLs, aunque debes vigilar el tamaño total del bundle para que no se dispare. Si tu aplicación usa muchos recursos, evalúa si puedes alojarlos en un CDN y referenciarlos por URL.
Probando la aplicación final
Para verificar que el archivo único funciona, crea un archivo test.html junto a tu index.js generado:
<!DOCTYPE html>
<html lang='es'>
<head>
<meta charset='UTF-8'>
<title>Prueba del bundle único</title>
</head>
<body>
<div id='root'></div>
<script src='./index.js'></script>
</body>
</html>Abre este HTML en el navegador. Si tu aplicación aparece sin errores, el proceso ha sido exitoso. Asegúrate de que no haya peticiones adicionales a archivos CSS o imágenes (salvo las que tú quieras mantener externas).
Usos prácticos en producción
Este método es el estándar de facto para widgets de terceros: chats de atención al cliente, calculadoras de hipotecas, reproductores de vídeo, formularios de suscripción o cualquier componente que deba incrustarse en páginas ajenas con una sola línea de código. También lo usan equipos que construyen microfrontends y necesitan publicar un único artefacto por módulo, simplificando el despliegue.
En extensiones de navegador, la carpeta de la extensión se reduce a un par de archivos, y se evitan dependencias de red. Incluso en contextos de IoT o aplicaciones embebidas, un solo archivo JS puede cargarse en entornos muy limitados.
Cómo HolaGPT te facilita el proceso
Cuando la configuración se vuelve densa (mezcla de Vite, Rollup, loaders, CSS inyectado), contar con un asistente que entienda el stack ahorra horas de debug. En HolaGPT, una plataforma de IA para profesionales hispanos, puedes pedir: «Dame una configuración de Vite para empaquetar un widget React en un único archivo con imágenes inline» y recibir una solución adaptada a tu caso. El chat te ayudará a refinar los detalles y te dará código listo para copiar, todo en español. Así aceleras el desarrollo sin sacrificar calidad.