Tema
npm y Vite
Los proyectos profesionales no se construyen sólo con un index.html y un app.js. Usan paquetes de terceros (librerías para gráficas, fechas, carruseles), un servidor de desarrollo que recarga al instante y un proceso de build que optimiza todo para producción. En esta lección aprenderás a usar npm y Vite, las herramientas estándar del desarrollo frontend moderno.
Concepto
- Node.js es JavaScript fuera del navegador. Aunque tu proyecto sea frontend, lo necesitas para ejecutar las herramientas.
- npm (Node Package Manager) es como una tienda de apps para código: más de 2 millones de paquetes que puedes instalar con un comando.
- Vite es una herramienta que te da un servidor de desarrollo ultrarrápido y empaqueta tu código para producción. Es como tener un asistente de cocina: mientras cocinas (desarrollas) te va pasando todo al instante, y al final emplata (optimiza) para servir al cliente.
Instalar Node.js y npm
- Descarga la versión LTS desde nodejs.org e instálala (npm viene incluido).
- Verifica en la terminal:
bash
node --version # v22.x.x o superior
npm --version # 10.x.xBuena práctica
Si trabajas en varios proyectos con versiones distintas de Node, usa un gestor de versiones: nvm (macOS/Linux), nvm-windows o fnm (todas las plataformas).
package.json: el DNI de tu proyecto
Cada proyecto con npm tiene un archivo package.json que describe el proyecto, sus dependencias y sus comandos.
bash
mkdir mi-proyecto
cd mi-proyecto
npm init -y # crea package.json con valores por defectojson
{
"name": "mi-proyecto",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint ."
},
"dependencies": {
"dayjs": "^1.11.13"
},
"devDependencies": {
"vite": "^6.0.0",
"eslint": "^9.0.0"
}
}"type": "module"→ usarimport/export(módulos ES) en Node.scripts→ atajos que ejecutas connpm run <nombre>.dependencies→ paquetes que tu app necesita para funcionar (llegan al usuario).devDependencies→ herramientas que sólo usas al desarrollar (Vite, ESLint, Prettier).
Instalar paquetes
bash
# Dependencia normal
npm install dayjs
npm i dayjs # forma corta
# Dependencia de desarrollo
npm install -D vite
npm i -D eslint prettier
# Una versión concreta
npm i dayjs@1.11.10
# Desinstalar
npm uninstall dayjs
# Instalar TODO lo que dice package.json (al clonar un proyecto)
npm install
# Ver paquetes desactualizados y actualizarlos
npm outdated
npm update
# Revisar vulnerabilidades conocidas
npm auditAl instalar se crean:
node_modules/: el código de los paquetes (¡puede pesar cientos de MB!).package-lock.json: las versiones exactas instaladas, para que todo el equipo tenga lo mismo.
Error común
Nunca subas node_modules a Git. Añádelo a .gitignore. Cualquiera puede regenerarlo con npm install. En cambio, package-lock.json sí se sube.
txt
# .gitignore
node_modules
dist
.env
.env.localVersiones semánticas
"dayjs": "^1.11.13" sigue el formato MAYOR.MENOR.PARCHE:
- PARCHE (1.11.13): corrección de bugs.
- MENOR (1.11.0): nuevas funciones compatibles.
- MAYOR (1.0.0): cambios que pueden romper tu código.
El ^ permite actualizar MENOR y PARCHE, pero no MAYOR. El ~ sólo permite PARCHE.
npx: ejecutar sin instalar
npx ejecuta un paquete sin instalarlo globalmente:
bash
npx serve . # servidor estático en la carpeta actual
npx prettier --write . # formatear todo el proyecto
npx eslint src # revisar el códigoScripts
bash
npm run dev # ejecuta "vite"
npm run build
npm run lint
npm test # "test" y "start" no necesitan "run"
npm startPuedes combinar scripts:
json
{
"scripts": {
"format": "prettier --write .",
"check": "npm run lint && npm run build"
}
}Crear un proyecto con Vite
bash
npm create vite@latest mi-tiendaEl asistente te pregunta el framework (elige Vanilla) y la variante (JavaScript o TypeScript). Luego:
bash
cd mi-tienda
npm install
npm run devAbre http://localhost:5173 y verás tu proyecto. Cada vez que guardes un archivo, el navegador se actualiza al instante (HMR, Hot Module Replacement), sin perder el estado.
Estructura del proyecto
txt
mi-tienda/
├── index.html ← punto de entrada (en la raíz, no en public/)
├── package.json
├── public/ ← archivos que se copian tal cual (favicon, robots.txt)
│ └── favicon.svg
└── src/
├── main.js ← tu JavaScript principal
├── style.css
└── counter.jshtml
<!-- index.html -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mi tienda</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>Lo que Vite te permite hacer
js
// src/main.js
// Importar CSS desde JavaScript
import './style.css';
// Importar paquetes de npm por su nombre (sin rutas ni extensiones)
import dayjs from 'dayjs';
import 'dayjs/locale/es';
dayjs.locale('es');
// Importar imágenes: Vite te da la URL final optimizada
import logoUrl from './assets/logo.svg';
// Importar JSON directamente
import productos from './data/productos.json';
// Tus módulos (la extensión .js es opcional con Vite)
import { formatearMoneda } from './utils/formato';
document.querySelector('#app').innerHTML = `
<img src="${logoUrl}" alt="Logo" width="64">
<p>Hoy es ${dayjs().format('dddd D [de] MMMM')}</p>
<p>${productos.length} productos desde ${formatearMoneda(349)}</p>
`;Variables de entorno
Para valores que cambian entre desarrollo y producción (URL de la API, claves públicas), crea archivos .env:
env
# .env (valores por defecto)
VITE_API_URL=https://jsonplaceholder.typicode.com
VITE_NOMBRE_APP=Mi Tienda
# .env.production (sólo al hacer build)
VITE_API_URL=https://api.mitienda.comjs
const API = import.meta.env.VITE_API_URL;
console.log(import.meta.env.MODE); // 'development' o 'production'
console.log(import.meta.env.DEV); // true en desarrolloSeguridad
Sólo las variables que empiezan con VITE_ llegan al navegador, y todas ellas son públicas: cualquiera puede verlas en el código final. Nunca pongas ahí contraseñas, claves secretas de APIs ni credenciales de base de datos.
Build para producción
bash
npm run buildVite genera la carpeta dist/ con tu sitio listo para producción:
- JavaScript minificado (sin espacios ni comentarios) y empaquetado.
- Código no usado eliminado (tree shaking).
- Archivos con hash en el nombre (
index-a1b2c3.js) para que el navegador no use versiones viejas en caché. - CSS optimizado e imágenes pequeñas convertidas en línea.
bash
npm run preview # sirve dist/ en local para probar el resultado finalDesplegar
La carpeta dist/ es un sitio estático: puedes subirla a cualquier hosting.
- Netlify / Vercel / Cloudflare Pages: conecta tu repositorio de GitHub; ellos ejecutan
npm run buildy publicandistautomáticamente en cada push. - Hosting compartido (cPanel, Apache): sube el contenido de
dist/apublic_htmlpor FTP o el administrador de archivos. - GitHub Pages: configura
baseen Vite si tu sitio vive en una subcarpeta.
js
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
base: '/mi-tienda/', // si se publica en https://usuario.github.io/mi-tienda/
server: { port: 3000, open: true },
build: { outDir: 'dist' }
});Error común
Subir la carpeta del proyecto completa (con src/ y node_modules/) al hosting. Al servidor sólo va el resultado del build: el contenido de dist/.
Configurar ESLint y Prettier en el proyecto
bash
npm i -D eslint @eslint/js globals prettier eslint-config-prettierjs
// eslint.config.js
import js from '@eslint/js';
import globals from 'globals';
import prettier from 'eslint-config-prettier';
export default [
{ ignores: ['dist'] },
js.configs.recommended,
prettier,
{
languageOptions: { globals: globals.browser },
rules: { 'no-unused-vars': 'warn', eqeqeq: 'error' }
}
];json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint .",
"format": "prettier --write ."
}
}Flujo de trabajo completo
bash
npm create vite@latest landing-cliente # 1. crear (Vanilla + JavaScript)
cd landing-cliente
npm install # 2. instalar
npm i -D eslint @eslint/js globals prettier eslint-config-prettier
git init && git add . && git commit -m "Proyecto inicial" # 3. versionar
npm run dev # 4. desarrollar
npm run lint # 5. revisar
npm run build # 6. construir
npm run preview # 7. probar el build
# 8. desplegar dist/ en Netlify, Vercel o tu hostingEjercicios
- Crea un proyecto con
npm init -y, instaladayjscomo dependencia yprettiercomo devDependency. Revisa cómo quedópackage.json. - Crea un proyecto Vite vanilla y cambia el contenido de
#apppara mostrar tu nombre y la fecha actual en español. - Mueve los datos de unos productos a
src/data/productos.jsone impórtalos para pintarlos en una lista. - Crea una variable de entorno
VITE_API_URLy úsala para hacer unfetcha/users. - Agrega un script
"check"que ejecute lint y build, y genera el build de producción.
Ver solución
bash
# 1
mkdir practica && cd practica
npm init -y
npm i dayjs
npm i -D prettier
# package.json ahora tiene "dependencies": { "dayjs": ... } y "devDependencies": { "prettier": ... }
# 2
npm create vite@latest mi-app -- --template vanilla
cd mi-app && npm install && npm run devjs
// 2 — src/main.js
import './style.css';
const hoy = new Date().toLocaleDateString('es-MX', { dateStyle: 'full' });
document.querySelector('#app').innerHTML = `<h1>Hola, soy Ana</h1><p>${hoy}</p>`;
// 3 — src/main.js
import productos from './data/productos.json';
const ul = document.createElement('ul');
productos.forEach((p) => {
const li = document.createElement('li');
li.textContent = `${p.nombre} - $${p.precio}`;
ul.append(li);
});
document.querySelector('#app').append(ul);
// 4 — .env: VITE_API_URL=https://jsonplaceholder.typicode.com
const r = await fetch(`${import.meta.env.VITE_API_URL}/users`);
const usuarios = await r.json();
console.log(usuarios);json
{
"scripts": {
"check": "npm run lint && npm run build"
}
}Resumen
- Node.js ejecuta las herramientas; npm instala paquetes y ejecuta scripts.
package.jsondescribe el proyecto;dependenciesvan a producción ydevDependenciesson sólo para desarrollar.node_modulesnunca va a Git;package-lock.jsonsí.- Vite:
npm create vite@latest,npm run dev(HMR),npm run build(generadist/) ynpm run preview. - Las variables
VITE_son públicas: nada secreto en el frontend. - Despliega sólo el contenido de
dist/.
Ya tienes las bases profesionales. Es momento de construir proyectos completos: Proyecto: lista de tareas. Y cuando termines los proyectos, da el siguiente paso con TypeScript.