learning-front

Nivel 4 · Tooling profesional: el entorno de un proyecto serio

ESLint y Prettier (y un vistazo a oxc)

Detectar errores y formatear el código de forma automática y consistente en equipo: ESLint con flat config (v9+), Prettier, cómo conviven con eslint-config-prettier, cómo automatizarlo, y un vistazo honesto a oxc/oxlint.

Dos problemas distintos#

Cuando trabajas en equipo sobre un proyecto de JavaScript, aparecen dos tipos de problemas que no tienen nada que ver entre sí:

Problemas de calidad: el código tiene patrones que probablemente son errores. Una variable que se declaró pero nunca se usa. Una comparación con == que puede dar sorpresas por la coerción. Una promesa sin await que se ignora. Estas cosas no son un problema de formato: son posibles bugs o código muerto.

Problemas de formato: cada persona del equipo escribe con comillas distintas, sangría diferente, con o sin punto y coma al final. El código funciona igual, pero los diffs de git se llenan de cambios de estilo que ocultan los cambios reales.

Son dos problemas distintos y tienen dos herramientas distintas:

  • Un linter (ESLint) analiza el código y señala los problemas de calidad. No toca el formato.
  • Un formateador (Prettier) reescribe el código con un estilo consistente. No evalúa la calidad.

No compiten. Se usan juntos.

ESLint#

ESLint es el linter estándar en el ecosistema JavaScript/TypeScript. Al ejecutar npx eslint . sobre un directorio, analiza cada fichero .js y .ts y señala los patrones que incumplen las reglas configuradas.

Qué detecta: variables sin usar, == en vez de ===, console.log olvidados en producción, promesas sin gestión de errores, importaciones circulares, y decenas de otros patrones que en un proyecto real causan bugs reales.

Flat config: desde ESLint v9.0.0, el fichero de configuración es eslint.config.js y es el formato por defecto. El formato antiguo (.eslintrc, .eslintrc.json) está deprecado; ESLint ya no lo busca. El nuevo formato es un fichero que exporta un array de objetos de configuración:

javascript
// eslint.config.js — flat config (por defecto desde ESLint v9)
// el paquete oficial con las reglas recomendadas
import js from '@eslint/js';

export default [
  // activa el conjunto de reglas recomendadas
  js.configs.recommended,
  {
    languageOptions: {
      // version de JavaScript a analizar
      ecmaVersion: 2024,
      // el proyecto usa import/export (ESM)
      sourceType: 'module',
    },
  },
];

El preset js.configs.recommended (del paquete @eslint/js) activa un conjunto razonado de reglas de calidad. Antes de ESLint v9, se usaba el string "eslint:recommended"; en flat config eso ya no funciona: hay que importar el paquete.

Instalación:

shell
npm install -D eslint @eslint/js

Cómo analiza ESLint tu código: cuando ejecutas eslint ., ESLint lee cada fichero y lo convierte en una representación interna que describe la estructura del programa: qué variables se declaran, qué funciones se llaman, en qué orden aparecen las expresiones. Sobre esa representación aplica cada regla: un chequeo automático que pregunta cosas como “¿hay alguna variable declarada que nunca se use?” o “¿se usa == en alguna comparación?”. Si la regla lo detecta, ESLint informa del fichero y la línea exacta.

Un plugin es un paquete npm que añade reglas que no vienen de serie en ESLint. Las reglas de ESLint base cubren JavaScript estándar; si necesitas reglas específicas para React (eslint-plugin-react), para ordenar imports (eslint-plugin-import) o para accesibilidad (eslint-plugin-jsx-a11y), instalas el plugin correspondiente y ESLint pasa a tener esas reglas disponibles. Lo verás cuando llegues a React en el nivel 6.

Reglas, error y warn: cada regla tiene un nivel de severidad:

javascript
// En el objeto 'rules' del flat config:
rules: {
  // falla npm run lint → la CI no pasa
  'no-unused-vars': 'error',
  // avisa pero no falla → la CI pasa aunque haya avisos
  eqeqeq: 'warn',
  // desactivada: en este proyecto los console.log son validos
  'no-console': 'off',
}

La diferencia entre 'error' y 'warn' importa: con 'warn' el comando termina con código de salida 0 (éxito), así que la CI pasa aunque haya avisos. En la práctica, los avisos que no bloquean tienden a acumularse y a ignorarse. La regla general en equipos: si una regla merece la pena, actívala como 'error'; si no, desactívala del todo.

eslint-disable: si en un caso concreto una regla no aplica, puedes desactivarla para esa línea. Úsalo con criterio y siempre con un comentario que justifique por qué:

javascript
// Una excepcion justificada: aqui si necesitamos == para comparar null y undefined
// eslint-disable-next-line eqeqeq -- null y undefined a la vez
if (valor == null) {
  return 'ausente';
}

Sin el comentario de por qué, el eslint-disable solo esconde el problema.

eslint . --fix: algunos problemas que ESLint detecta tienen una corrección mecánica y segura que puede aplicar él solo. Al añadir --fix al comando, ESLint reescribe los ficheros directamente con esas correcciones:

shell
npx eslint . --fix

Lo que arregla solo son problemas de formato o transformaciones sin ambigüedad: comillas, punto y coma, espacios. Lo que no puede arreglar son problemas que requieren decisión humana: una variable sin usar (no sabe si hay que eliminarla o usarla), un == que podría ser un === (no sabe si la coerción era intencionada). Para esos, ESLint solo informa; el arreglo es tuyo.

En la práctica, --fix es útil cuando importas un proyecto heredado con muchos avisos de formato: lo corres una vez, el ruido desaparece, y lo que queda son los problemas reales.

Prettier#

Prettier es un formateador opinado: no te da opciones sobre cómo debe quedar el código, lo decide por ti. Cuando lo ejecutas sobre un fichero, lo reescribe con su estilo. El resultado es siempre el mismo independientemente de quién lo haya escrito antes.

Eso es lo valioso: quita las discusiones de estilo del equipo. Si Prettier decide las comillas, nadie pierde tiempo en una pull request comentando si deberían ser simples o dobles.

Instalación:

shell
npm install -D prettier

Configuración con .prettierrc: aunque Prettier es opinado, puedes ajustar unas pocas opciones:

json
{
  "singleQuote": true,
  "semi": true,
  "printWidth": 90,
  "trailingComma": "es5"
}

singleQuote usa comillas simples. semi añade punto y coma al final. printWidth es el límite de caracteres por línea. trailingComma pone coma final en el último elemento de arrays y objetos (lo que hace los diffs de git más limpios).

Format-on-save: la forma más cómoda de usar Prettier es que el editor lo corra al guardar. En VSCode (que vimos en el nivel 0), añade al fichero .vscode/settings.json del proyecto:

json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

Con esto, cada vez que guardas un fichero, Prettier lo formatea al instante. El equipo no tiene que acordarse de correr el comando.

Cómo conviven#

ESLint tiene algunas reglas que también afectan al formato del código: sangría, longitud de línea, comillas. Si tanto ESLint como Prettier intentan controlar eso, entran en conflicto: uno quiere comillas dobles, el otro simples, y los errores son confusos.

La solución es eslint-config-prettier: apaga todas las reglas de ESLint que afectan al formato, porque Prettier ya se ocupa de eso:

shell
npm install -D eslint-config-prettier
javascript
// eslint.config.js con convivencia
import js from '@eslint/js';
// apaga las reglas de formato de ESLint
import prettier from 'eslint-config-prettier';

export default [
  // ESLint cuida bugs y malas practicas
  js.configs.recommended,
  // va el ULTIMO: sus desactivaciones sobreescriben lo anterior
  prettier,
  {
    languageOptions: {
      ecmaVersion: 2024,
      sourceType: 'module',
    },
  },
];

eslint-config-prettier va el último en el array porque el flat config aplica las configuraciones en orden: si lo pones antes, una configuración posterior podría reactivar las reglas que quieres apagar.

Con esto: ESLint cuida la calidad del código, Prettier cuida el formato, y nunca se pisan.

Nota: eslint-plugin-prettier — si buscas en tutoriales verás también un paquete llamado eslint-plugin-prettier. Este hace algo distinto: corre Prettier como si fuera una regla de ESLint, de modo que los fallos de formato aparecen como errores del linter. Hoy (2026) se desaconseja porque hace el linting más lento y los mensajes de error son confusos (“Delete ·” no es un error útil). La forma correcta es la que hemos visto: Prettier y ESLint corren por separado, y eslint-config-prettier (sin plugin) se limita a desactivar las reglas de formato de ESLint para que no choquen.

Automatizar#

El par ESLint + Prettier solo tiene valor si se corre de verdad. Hay tres momentos donde se suele automatizar:

Scripts en package.json:

json
"scripts": {
  "lint":   "eslint .",
  "format": "prettier --write ."
}

Ahora cualquier persona del equipo puede ejecutar npm run lint para ver si hay problemas y npm run format para formatear todo el proyecto.

Pre-commit con husky y lint-staged: un hook de git es un script que git ejecuta automáticamente en ciertos momentos; el hook pre-commit, por ejemplo, se dispara justo antes de cada git commit. Puedes usarlo para garantizar que nadie sube código sin lintear. husky gestiona esos hooks desde package.json; lint-staged limita el análisis a los ficheros que van en ese commit (no todo el proyecto, que podría ser lento). Verás este patrón en proyectos reales:

shell
npm install -D husky lint-staged

El nivel 8 del curso cubre CI/CD en detalle. Por ahora quédate con la idea: hay formas de hacer que el linter y el formateador corran automáticamente antes de que el código llegue al repositorio.

CI: en GitHub Actions (que veremos en el nivel 8), añadir un paso de npm run lint al workflow es la forma de garantizar que ningún pull request rompa las reglas. El pipeline falla si el linter detecta errores.

Lo que viene: oxc#

oxc es un conjunto de herramientas de JavaScript escrito en Rust. Es parte de un movimiento más amplio en el ecosistema: reescribir el tooling en lenguajes compilados para ganar velocidad.

Ya viste oxc en el capítulo de Vite: oxc es el minificador por defecto de Vite 8 (reemplaza a esbuild para esa tarea). Su lado linter, oxlint, puede ser órdenes de magnitud más rápido que ESLint en repositorios grandes, porque analiza los ficheros en paralelo aprovechando Rust.

El trade-off honesto en 2026:

  • A favor: velocidad real. En un monorepo con miles de ficheros, la diferencia es perceptible.
  • En contra: el ecosistema de plugins de ESLint es mucho más maduro. Los plugins para React, TypeScript, accesibilidad, Tailwind o imports que se usan en casi cualquier proyecto tienen años de desarrollo en ESLint y están bien probados. En oxlint, el ecosistema es todavía pequeño.

ESLint + Prettier siguen siendo el estándar de equipo en 2026 por madurez, ecosistema y documentación. oxlint es “lo que viene”: vale la pena tenerlo en el radar, pero la decisión de adoptarlo depende del tamaño del repositorio y de si los plugins que necesitas están disponibles.

Pruébalo#

El siguiente playground ejecuta código con un bug que ESLint detectaría con la regla eqeqeq. Observa qué imprime en la consola: el resultado debería sorprenderte.

El capítulo siguiente, Clean code: SOLID, KISS, DRY y patrones, da un paso atrás: hasta aquí has aprendido a montar y configurar la maquinaria del proyecto; ahora toca hablar de cómo escribir el código que va dentro de esa maquinaria para que aguante el tiempo y sea legible para cualquiera del equipo.

Comprueba lo que sabes#

Pregunta 1 de 5

¿Cuál es la diferencia entre un linter y un formateador?

Tu turno#

Abre el Team Builder que llevas del capítulo anterior y añade ESLint y Prettier desde cero. El ejercicio se trabaja en tu entorno local.

Qué esperar al ejecutar eslint . — en el repositorio del ejercicio hay un fichero exercises/nivel-4/eslint-y-prettier/starter/equipo.js con tres violaciones deliberadas. Cópialo a tu proyecto, configura ESLint con las reglas no-unused-vars y eqeqeq, y ejecuta eslint .. Deberías ver una salida parecida a esta:

texto
equipo.js
  17:7  error  'heroesReserva' is defined but never used  no-unused-vars
  24:21  error  Expected '===' and instead saw '=='       eqeqeq

✖ 2 problems (2 errors, 0 warnings)

Cuando hayas arreglado los dos problemas en el código (sin usar eslint-disable), la salida debe ser:

texto
equipo.js: no problems found

Ese es el estado limpio que pide el tier excelente.

Ejercicio · hazlo en local

ESLint y Prettier en el Team Builder

Añade ESLint y Prettier al Team Builder que llevas del capítulo anterior. El objetivo es que cualquier compañero que clone el repositorio pueda ejecutar npm run lint y saber al instante si el código tiene problemas, y npm run format para dejarlo formateado de forma consistente.

Paso 1: Un linter y un formateador que funcionan

  • Instalas `eslint` y `@eslint/js` como devDependencies y creas `eslint.config.js` con flat config.
  • Instalas `prettier` y creas `.prettierrc` con al menos tres opciones declaradas.
  • Añades los scripts `"lint": "eslint ."` y `"format": "prettier --write ."` al `package.json`.
  • `npm run lint` termina sin errores.

Cómo hacerlo en local

Clona el repositorio del curso, entra en la carpeta del ejercicio y abre el index.html en tu navegador. Toda tu solución va en solucion.js.

git clone <repo>
cd exercises/nivel-4/eslint-y-prettier
# abre index.html en el navegador y edita solucion.js
Ver soluciones
// eslint.config.js (flat config — el formato por defecto desde ESLint v9)
// el paquete oficial con las reglas recomendadas
import js from '@eslint/js';

export default [
  // activa el conjunto de reglas recomendadas
  js.configs.recommended,
  {
    languageOptions: {
      // version de JavaScript a analizar
      ecmaVersion: 2024,
      // el proyecto usa import/export (ESM)
      sourceType: 'module',
    },
  },
];

// ───── .prettierrc (fichero aparte, en JSON) ─────
// {
//   "singleQuote": true,
//   "semi": true,
//   "printWidth": 90,
//   "trailingComma": "es5"
// }

Por qué este nivel

  • ESLint instalado con flat config y el preset recomendado: ya tienes una red de calidad activa. npm run lint pasa, que es la base de un proyecto de equipo.
  • Prettier configurado con opciones explícitas: desde ahora el equipo no debate sobre comillas ni punto y coma, el formateador decide.