JavaScript

JavaScript

Tutorial JavaScript: Configuración de Bundlers como Vite

JavaScript y los bundlers, herramientas esenciales para optimizar aplicaciones web modernas garantizando modularidad, rendimiento y compatibilidad.

Aprende JavaScript y certifícate

¿Qué es y para qué sirve un bundler?

Un bundler es una herramienta de desarrollo que toma todos los archivos y recursos de tu aplicación JavaScript y los empaqueta en uno o varios archivos optimizados para producción. Imagina que tienes decenas o cientos de archivos JavaScript, CSS, imágenes y otros recursos distribuidos en una estructura de carpetas compleja; un bundler los procesa, optimiza y combina para que puedan ser entregados eficientemente al navegador.

Problemas que resuelven los bundlers

En el desarrollo web moderno nos enfrentamos a varios desafíos que los bundlers ayudan a resolver:

  • Modularización del código: Al trabajar con aplicaciones complejas, necesitamos dividir nuestro código en módulos independientes.
// math.js
export function sum(a, b) {
 return a + b;
}

// app.js
import { sum } from './math.js';
console.log(sum(5, 3)); // 8
  • Dependencias: Las aplicaciones modernas utilizan numerosas bibliotecas externas que deben gestionarse correctamente.

  • Compatibilidad entre navegadores: No todos los navegadores soportan las últimas características de JavaScript.

  • Optimización de recursos: Cargar muchos archivos pequeños es ineficiente debido a las múltiples peticiones HTTP.

  • Procesamiento de diferentes tipos de archivos: Además de JavaScript, necesitamos manejar CSS, imágenes, fuentes, etc.

Funcionalidades principales de un bundler

Los bundlers modernos ofrecen varias capacidades esenciales:

  • Resolución de dependencias: Analizan las importaciones y exportaciones para crear un grafo de dependencias.
// El bundler detecta esta dependencia y la incluye en el paquete final
import { createApp } from 'vue';
  • Transformación de código: Convierten código moderno en versiones compatibles con navegadores antiguos.

  • Minificación y optimización: Reducen el tamaño de los archivos eliminando espacios, comentarios y acortando nombres de variables.

// Código original
function calculateTotal(items) {
 return items.reduce((total, item) => total + item.price, 0);
}

// Código minificado
function c(i){return i.reduce((t,i)=>t+i.price,0)}
  • Code splitting: Dividen el código en múltiples paquetes que pueden cargarse bajo demanda.

  • Hot Module Replacement (HMR): Permiten actualizar módulos en tiempo real durante el desarrollo sin recargar toda la página.

  • Tree shaking: Eliminan código no utilizado para reducir el tamaño final.

// Biblioteca con múltiples funciones
import { useState } from 'react'; // Solo se incluirá useState en el bundle final

Bundlers populares

Existen varios bundlers en el ecosistema JavaScript, cada uno con sus propias características:

  • Webpack: El más completo y configurable, aunque con una curva de aprendizaje pronunciada.

  • Rollup: Especializado en bibliotecas, con excelente soporte para tree shaking.

  • Parcel: Enfocado en la simplicidad, con configuración cero.

  • esbuild: Destaca por su velocidad extremadamente rápida.

  • Vite: Combina un servidor de desarrollo basado en ESM nativo con un proceso de compilación potente.

Beneficios de usar un bundler

La implementación de un bundler en tu flujo de trabajo ofrece ventajas significativas:

  • Mejor rendimiento: Menos solicitudes HTTP y archivos más pequeños significan cargas más rápidas.

  • Desarrollo más eficiente: Características como HMR aceleran el ciclo de desarrollo.

  • Organización del código: Facilita la estructuración del proyecto en módulos reutilizables.

  • Compatibilidad: Permite usar características modernas de JavaScript sin preocuparse por la compatibilidad.

  • Optimización automática: Procesos como minificación y compresión se realizan automáticamente.

Flujo de trabajo básico con un bundler

El proceso típico al trabajar con un bundler incluye:

  1. Configuración: Definir cómo debe procesar los diferentes tipos de archivos.
// Ejemplo simplificado de configuración
export default {
 entry: './src/main.js',
 output: {
   filename: 'bundle.js',
   path: '/dist'
 }
}
  1. Desarrollo: Utilizar el servidor de desarrollo con recarga en caliente.

  2. Compilación: Generar archivos optimizados para producción.

  3. Despliegue: Publicar los archivos compilados en un servidor web.

¿Cuándo necesitas un bundler?

No todos los proyectos requieren un bundler. Considera usar uno cuando:

  • Trabajas con aplicaciones de una sola página (SPA).
  • Necesitas gestionar múltiples dependencias externas.
  • Utilizas frameworks modernos como React, Vue o Angular.
  • Requieres optimización avanzada para producción.
  • Trabajas con equipos grandes donde la modularización es crucial.

Para proyectos pequeños o sitios estáticos simples, un bundler podría ser innecesariamente complejo. Sin embargo, para aplicaciones web modernas, se ha convertido en una herramienta prácticamente indispensable en el flujo de desarrollo.

Primeros pasos con Vite

Vite (pronunciado como "veet", que significa "rápido" en francés) es un bundler moderno que destaca por su velocidad extraordinaria y su enfoque en la experiencia de desarrollo. A diferencia de bundlers tradicionales, Vite aprovecha los módulos ES nativos del navegador durante el desarrollo, lo que elimina la necesidad de empaquetar todo el código cada vez que realizas un cambio.

Instalación de Vite

Para comenzar a utilizar Vite, necesitas tener Node.js instalado (versión 14.18+ o 16+). Puedes crear un nuevo proyecto utilizando npm, yarn o pnpm:

# Usando npm
npm create vite@latest my-vite-app

# Usando yarn
yarn create vite my-vite-app

# Usando pnpm
pnpm create vite my-vite-app

Al ejecutar este comando, se iniciará un asistente interactivo que te permitirá seleccionar un framework (como React, Vue, Svelte) o vanilla JavaScript, así como la variante de TypeScript si lo deseas:

✔ Select a framework: › Vanilla
✔ Select a variant: › JavaScript

Estructura del proyecto

Una vez creado el proyecto, obtendrás una estructura básica similar a esta:

my-vite-app/
├── node_modules/
├── public/
│   └── favicon.ico
├── src/
│   ├── main.js
│   └── style.css
├── index.html
├── package.json
└── vite.config.js

Aspectos clave de esta estructura:

  • El archivo index.html está en la raíz del proyecto, no en una carpeta pública como en otros bundlers.
  • El directorio src/ contiene tu código fuente JavaScript.
  • La carpeta public/ almacena archivos estáticos que se copiarán directamente a la carpeta de distribución.

Iniciando el servidor de desarrollo

Para iniciar el servidor de desarrollo, navega a la carpeta del proyecto y ejecuta:

# Navegar al directorio del proyecto
cd my-vite-app

# Instalar dependencias
npm install

# Iniciar servidor de desarrollo
npm run dev

Verás un mensaje indicando que el servidor está funcionando, generalmente en http://localhost:5173. Al abrir esta URL en tu navegador, podrás ver tu aplicación en funcionamiento.

Modificando el proyecto

Vamos a realizar algunos cambios básicos para entender cómo funciona Vite. Abre el archivo src/main.js y modifícalo:

// src/main.js
import './style.css'

document.querySelector('#app').innerHTML = `
 <h1>Hello Vite!</h1>
 <div class="card">
   <button id="counter" type="button">Count: 0</button>
 </div>
`

// Añadimos funcionalidad al botón
const counterButton = document.querySelector('#counter')
let count = 0

counterButton.addEventListener('click', () => {
 count++
 counterButton.textContent = `Count: ${count}`
})

Al guardar estos cambios, notarás que la página se actualiza instantáneamente sin recargar completamente, gracias al Hot Module Replacement (HMR) integrado en Vite.

Configuración básica

Vite está diseñado para funcionar con configuración mínima, pero puedes personalizarlo según tus necesidades mediante el archivo vite.config.js:

// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
 // Cambiar el puerto del servidor
 server: {
   port: 3000
 },
 // Configurar alias para importaciones
 resolve: {
   alias: {
     '@': '/src'
   }
 }
})

Esta configuración cambia el puerto del servidor a 3000 y crea un alias @ que apunta al directorio src, permitiéndote importar módulos de forma más limpia:

// En lugar de:
import { helper } from '../../utils/helper'

// Puedes usar:
import { helper } from '@/utils/helper'

Añadiendo dependencias

Puedes instalar y utilizar cualquier paquete npm en tu proyecto Vite. Por ejemplo, añadamos una biblioteca de utilidades como Lodash:

npm install lodash-es

Luego, puedes importarla en tu código:

// src/main.js
import { debounce } from 'lodash-es'

// Crear una función con debounce
const handleSearch = debounce((event) => {
 console.log('Searching for:', event.target.value)
}, 300)

// Añadir un campo de búsqueda
document.querySelector('#app').innerHTML += `
 <div class="search">
   <input type="text" placeholder="Search..." id="search">
 </div>
`

document.querySelector('#search').addEventListener('input', handleSearch)

Vite optimizará automáticamente estas importaciones, incluyendo solo el código necesario en el bundle final gracias al tree shaking.

Trabajando con archivos estáticos

Vite maneja diferentes tipos de archivos de forma nativa. Por ejemplo, puedes importar imágenes directamente en tu JavaScript:

// Importar una imagen
import logoUrl from './assets/logo.png'

// Añadirla al DOM
const logo = document.createElement('img')
logo.src = logoUrl
logo.alt = 'Logo'
document.querySelector('#app').appendChild(logo)

También puedes colocar archivos en la carpeta public/ para que sean servidos directamente:

<!-- Referencia a un archivo en public/ -->
<link rel="icon" href="/favicon.ico" />

Uso de CSS y preprocesadores

Vite soporta la importación directa de CSS y varios preprocesadores. Para CSS normal:

// Importar CSS
import './style.css'

Si quieres usar Sass, solo necesitas instalar el preprocesador:

npm install -D sass

Y luego puedes importar archivos .scss directamente:

// Importar SCSS
import './style.scss'

Vite detectará automáticamente el preprocesador instalado y procesará los archivos correctamente.

Plugins básicos

El ecosistema de Vite incluye numerosos plugins que extienden su funcionalidad. Por ejemplo, para añadir soporte para archivos SVG como componentes React:

npm install -D vite-plugin-react-svg

Luego, configúralo en tu vite.config.js:

import { defineConfig } from 'vite'
import reactSvgPlugin from 'vite-plugin-react-svg'

export default defineConfig({
 plugins: [
   reactSvgPlugin({
     defaultExport: 'component'
   })
 ]
})

Con esta configuración, podrás importar SVGs como componentes React:

import Logo from './assets/logo.svg'

// Usar como componente
function Header() {
 return <Logo className="header-logo" />
}

Desarrollo y compilación

Una vez configurado Vite y familiarizado con su entorno de desarrollo, es fundamental entender los comandos esenciales que utilizarás durante el ciclo de vida de tu proyecto. Vite proporciona un conjunto de herramientas optimizadas tanto para el desarrollo ágil como para la compilación eficiente de aplicaciones listas para producción.

Comandos de desarrollo

El flujo de trabajo de desarrollo con Vite se centra en proporcionar una experiencia rápida y fluida. Los comandos principales que utilizarás durante esta fase son:

  • Iniciar el servidor de desarrollo:
npm run dev
# o
npx vite

Este comando inicia el servidor de desarrollo con Hot Module Replacement (HMR) activado por defecto. Cuando ejecutas este comando, Vite muestra información útil en la terminal:

 VITE v4.4.9  ready in 237 ms

 ➜  Local:   http://localhost:5173/
 ➜  Network: use --host to expose
 ➜  press h to show help
  • Opciones del servidor de desarrollo:

Puedes personalizar el comportamiento del servidor añadiendo flags al comando:

# Exponer en la red local (útil para pruebas en dispositivos)
npm run dev -- --host

# Cambiar el puerto
npm run dev -- --port 3000

# Abrir automáticamente el navegador
npm run dev -- --open
  • Modo de depuración:

Si necesitas información más detallada sobre lo que está ocurriendo internamente:

# Activar logs de depuración
npm run dev -- --debug

Comandos de compilación

Cuando tu aplicación está lista para ser desplegada, necesitas compilarla para producción. Vite optimiza automáticamente tu código, aplicando minificación, tree-shaking y otras técnicas para reducir el tamaño del bundle final.

  • Compilar para producción:
npm run build
# o
npx vite build

Este comando genera una versión optimizada de tu aplicación en la carpeta dist/ por defecto. La salida en la terminal te mostrará información sobre el proceso:

vite v4.4.9 building for production...
✓ 94 modules transformed.
dist/index.html                   0.49 KiB │ gzip: 0.32 KiB
dist/assets/logo-5d5d9eae.svg     0.14 KiB │ gzip: 0.14 KiB
dist/assets/index-92d87d34.css    1.33 KiB │ gzip: 0.70 KiB
dist/assets/index-d526a0c5.js   142.95 KiB │ gzip: 45.30 KiB
  • Personalizar la compilación:

Puedes ajustar el proceso de compilación mediante opciones:

# Especificar un directorio de salida diferente
npm run build -- --outDir my-dist

# Generar reportes de tamaño de bundle
npm run build -- --reportCompressedSize
  • Modo de compilación específico:
# Compilar para un entorno específico
npm run build -- --mode staging

Previsualización de la compilación

Antes de desplegar tu aplicación, es recomendable verificar que la versión compilada funciona correctamente. Vite incluye un comando específico para esto:

npm run preview
# o
npx vite preview

Este comando inicia un servidor local que sirve los archivos de la carpeta dist/, simulando un entorno de producción:

 ➜  Local:   http://localhost:4173/
 ➜  Network: use --host to expose

La previsualización es útil para detectar problemas que solo aparecen en el código compilado, como rutas incorrectas o problemas de optimización.

Configuración de entornos

Vite permite definir variables de entorno para diferentes contextos de ejecución. Esto es especialmente útil para manejar configuraciones específicas por entorno:

  • Archivos de entorno:

Puedes crear diferentes archivos para cada entorno:

.env                # Variables para todos los entornos
.env.local          # Variables locales (ignoradas en git)
.env.development    # Solo para desarrollo
.env.production     # Solo para producción

Ejemplo de un archivo .env.production:

VITE_API_URL=https://api.example.com
VITE_DEBUG_MODE=false
  • Acceso a variables de entorno:

En tu código, puedes acceder a estas variables mediante el objeto import.meta.env:

// Solo las variables con prefijo VITE_ son accesibles
const apiUrl = import.meta.env.VITE_API_URL;

fetch(`${apiUrl}/users`)
 .then(response => response.json())
 .then(data => console.log(data));

Optimización avanzada

Durante la compilación, Vite aplica varias optimizaciones automáticas, pero también puedes configurar aspectos específicos:

  • División de código (code splitting):

Vite implementa automáticamente code splitting basado en los puntos de entrada y las importaciones dinámicas:

// Esta importación se cargará bajo demanda
const loadFeature = async () => {
 const { setupFeature } = await import('./features/special-feature.js');
 setupFeature();
};

document.querySelector('#load-feature').addEventListener('click', loadFeature);
  • Pre-empaquetado de dependencias:

Vite pre-empaqueta las dependencias para mejorar el rendimiento:

// vite.config.js
export default defineConfig({
 optimizeDeps: {
   include: ['lodash-es', 'vue'], // Dependencias a pre-empaquetar
   exclude: ['slow-dependency']   // Dependencias a excluir
 }
})
  • Configuración de rollup:

Puedes ajustar la configuración de Rollup (el bundler que Vite usa para producción):

// vite.config.js
export default defineConfig({
 build: {
   rollupOptions: {
     output: {
       manualChunks: {
         vendor: ['react', 'react-dom'],
         utils: ['./src/utils/format.js', './src/utils/helpers.js']
       }
     }
   }
 }
})

Integración con herramientas de CI/CD

Para automatizar el proceso de compilación en entornos de integración continua, puedes utilizar los comandos de Vite en tus scripts:

// package.json
{
 "scripts": {
   "build:ci": "vite build --mode production",
   "test:e2e": "start-server-and-test 'vite preview' http://localhost:4173 'cypress run'"
 }
}

Un flujo típico en un pipeline de CI podría ser:

# Ejemplo simplificado de GitHub Actions
jobs:
 build:
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v3
     - uses: actions/setup-node@v3
       with:
         node-version: 16
     - run: npm ci
     - run: npm run build:ci
     - name: Archive production artifacts
       uses: actions/upload-artifact@v3
       with:
         name: dist
         path: dist

Solución de problemas comunes

Durante el desarrollo y compilación pueden surgir algunos problemas habituales:

  • Errores de importación:
# Limpiar la caché de Vite
npm run dev -- --force
  • Problemas con dependencias:
# Reconstruir el directorio node_modules
rm -rf node_modules
npm install
  • Verificar la compilación en modo debug:
# Ver más información sobre el proceso de build
npm run build -- --debug

Estos comandos esenciales te permitirán aprovechar al máximo las capacidades de Vite tanto en desarrollo como en la preparación de tu aplicación para producción, manteniendo un flujo de trabajo eficiente y optimizado.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende JavaScript online

Ejercicios de esta lección Configuración de Bundlers como Vite

Evalúa tus conocimientos de esta lección Configuración de Bundlers como Vite con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Funciones flecha

JavaScript
Puzzle

Polimorfismo

JavaScript
Test

Array

JavaScript
Código

Transformación con map()

JavaScript
Test

Gestor de tareas con JavaScript

JavaScript
Proyecto

Manipulación DOM

JavaScript
Test

Funciones

JavaScript
Test

Funciones flecha

JavaScript
Código

Async / Await

JavaScript
Código

Creación y uso de variables

JavaScript
Test

Excepciones

JavaScript
Puzzle

Promises

JavaScript
Código

Funciones cierre (closure)

JavaScript
Test

Herencia

JavaScript
Puzzle

Herencia

JavaScript
Test

Estructuras de control

JavaScript
Código

Selección de elementos DOM

JavaScript
Test

Modificación de elementos DOM

JavaScript
Test

Filtrado con filter() y find()

JavaScript
Test

Funciones cierre (closure)

JavaScript
Puzzle

Funciones

JavaScript
Puzzle

Mapas con Map

JavaScript
Test

Reducción con reduce()

JavaScript
Test

Callbacks

JavaScript
Puzzle

Manipulación DOM

JavaScript
Puzzle

Promises

JavaScript
Test

Async / Await

JavaScript
Test

Eventos del DOM

JavaScript
Puzzle

Async / Await

JavaScript
Puzzle

Promises

JavaScript
Puzzle

Filtrado con filter() y find()

JavaScript
Código

Callbacks

JavaScript
Test

Creación de clases y objetos Restaurante

JavaScript
Código

Reducción con reduce()

JavaScript
Código

Filtrado con filter() y find()

JavaScript
Puzzle

Reducción con reduce()

JavaScript
Puzzle

Conjuntos con Set

JavaScript
Puzzle

Herencia de clases

JavaScript
Código

Eventos del DOM

JavaScript
Test

Clases y objetos

JavaScript
Puzzle

Modificación de elementos DOM

JavaScript
Puzzle

Mapas con Map

JavaScript
Puzzle

Introducción a JavaScript

JavaScript
Test

Funciones

JavaScript
Código

Tipos de datos

JavaScript
Test

Clases y objetos

JavaScript
Test

Array

JavaScript
Test

Conjuntos con Set

JavaScript
Test

Array

JavaScript
Puzzle

Encapsulación

JavaScript
Puzzle

Clases y objetos

JavaScript
Código

Uso de operadores

JavaScript
Puzzle

Uso de operadores

JavaScript
Test

Estructuras de control

JavaScript
Test

Excepciones

JavaScript
Test

Transformación con map()

JavaScript
Puzzle

Funciones flecha

JavaScript
Test

Selección de elementos DOM

JavaScript
Puzzle

Encapsulación

JavaScript
Test

Mapas con Map

JavaScript
Código

Creación y uso de variables

JavaScript
Puzzle

Polimorfismo

JavaScript
Puzzle

Tipos de datos

JavaScript
Puzzle

Estructuras de control

JavaScript
Puzzle

Todas las lecciones de JavaScript

Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a JavaScript y certifícate

Certificados de superación de JavaScript

Supera todos los ejercicios de programación del curso de JavaScript y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el concepto y la función de los bundlers en el desarrollo web.
  • Identificar problemas que resuelven como modularización del código y compatibilidad entre navegadores.
  • Familiarizarse con las capacidades esenciales de los bundlers, como la minificación y el tree shaking.
  • Conocer bundlers populares como Webpack, Rollup, Parcel, esbuild y Vite.
  • Reconocer los beneficios de implementar un bundler en el flujo de trabajo.
  • Seguir un flujo de trabajo básico desde la configuración hasta el despliegue de aplicaciones.
  • Decidir cuándo es necesario utilizar un bundler en un proyecto.