Escuela Frontend
JavaScript

Configura ESLint, Prettier y Git Hooks en tu Próximo Proyecto de Javascript

Alejandro Ñáñez
Autor
Alejandro Ñáñez

A medida que las aplicaciones en JavaScript se vuelven más complejas, vamos a necesitar herramientas que aseguren la calidad del código que escribimos. Necesitaremos usar estas herramientas especialmente cuando nuestro proyecto crezca más allá de un par de archivos, o cuando trabajemos en equipo con otros desarrolladores. Además, tener configurado nuestro editor de manera adecuada nos permitirá disminuir el "feedback loop" en el proceso de desarrollo.

¿Qué aprenderás?

En este artículo veremos qué son y cómo funcionan las siguientes herramientas:

Al final de este artículo, entenderás:

  • Cómo crear una aplicación JavaScript Vanilla utilizando Vite.js
  • Cómo configurar ESLint
  • Cómo configurar Prettier
  • Cómo configurar Git Hooks a través de Husky
  • Cómo configurar VSCode para que reporte los errores y auto-formatee tu código

Prerrequisitos

Utilizaremos Vite.js para crear nuestro nuevo proyecto, aunque puedes configurar cualquier proyecto existente siguiendo los mismos pasos. Para que Vite funcione, debes tener instalado:

  • npmCómo instalar
  • node >= 12.0.0
  • VSCode - En este artículo cubriremos solamente VSCode, si utilizas otro editor/IDE, te recomiendo ver su documentación para poder configurar eslint y prettier

Outline

  • Crearemos una aplicación JavaScript Vanilla utilizando Vite.js
  • Configuraremos eslint
  • Configuraremos prettier
  • Configuraremos Git hooks utilizando Husky
  • Configuraremos VSCode para que funcione con nuestras herramientas.

Para ver la aplicación de prueba finalizada sigue los siguientes pasos:

# Clonar el repositorio
git clone https://github.com/alejandronanez/javascript-tooling
# Entrar en el proyecto
cd javascript-tooling
# Instalar las dependencias
npm install
# Correr eslint
npm run lint
# Correr prettier
npm run prettier

Crear la aplicación

Empecemos creando la aplicación

npm init @vitejs/app javascript-tooling

Después de ejecutar este comando, Vite.js te mostrará una lista de opciones para tu proyecto. Debes seleccionar vanilla

Después, Vite.js te pide escoger una variante (Vanilla vs Typescript), selecciona vanilla

Cuando termines, Vite.js te mostrará el siguiente mensaje

Ahora, lo siguiente que debemos hacer es entrar al proyecto e instalar las dependencias

cd javascript-tooling
npm install
# No es necesario correr npm run dev por ahora.
# Pero puedes hacerlo, no va a afectar en nada el flujo de trabajo.
npm run dev # (opcional)

Configurar ESLint

¿Para qué sirve ESLint?

ESLint analiza estáticamente nuestro código y nos dice qué reglas no estamos cumpliendo. Esto es útil para que sepamos qué errores estamos cometiendo antes de subir nuestro código a nuestro control de versiones (Github/Gitlab/Bitbucket) - es más, podemos interrumpir automáticamente un commit si tenemos errores de ESLint. Hablaremos de eso más adelante.

ESLint funciona a través de reglas, acá podemos verlas todas. Nosotros podemos escoger qué reglas utilizar y cuáles no, dependiendo de nuestras necesidades. Pero ¿cómo sabemos qué reglas necesitamos y cuáles no si hay muchas reglas para escoger? Afortunadamente, existe un set de reglas predeterminadas definidas por el equipo de ESLint llamadas eslint:recommended, acá podemos ver más al respecto. También vale la pena mencionar que eslint:recommended no es el único set de reglas existente, también podemos crear nuestro propio set de reglas. Por ejemplo, en Zapier (mi actual empleador) tenemos un set de reglas que se ajusta a nuestras necesidades. Otro set de reglas muy popular es el de Airbnb

Instalar ESLint en nuestra aplicación

# Instalemos ESLint como un devDependency
npm install eslint --save-dev
# Ahora podremos configurar eslint usando npx
npx eslint --init

Una vez escribimos el último comando, ESLint nos preguntará cómo queremos configurarlo en nuestro proyecto. Escojamos la segunda opción: "To check syntax and find problems". En nuestro caso, Prettier se encargará de asegurarse que sigamos un estilo de código consistente.

Como nuestra aplicación está utilizando "JavaScript Modules (import/export)", seleccionamos la primera opción en la siguiente pregunta

Escojamos "None of these" en la siguiente pregunta sobre qué framework estamos utilizando

Respondamos que "No usamos TypeScript"

Luego, seleccionemos "Browser" - si fuéramos a utilizar Node, deberíamos seleccionar las dos opciones.

Y, por último, escojamos "JSON" como el formato del archivo que utilizaremos para nuestra configuración

Una vez terminemos de contestar todas las preguntas, se creará un archivo .eslintrc.json que contendrá la configuración correspondiente.

Si abrimos el archivo, esto es lo que contiene:

{
"env": {
"browser": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {}
}

Corriendo ESLint en nuestro proyecto

Vamos a modificar el archivo main.js, borremos todo su contenido, agregamos la siguiente línea y guardamos el archivo.

const nombre = "Escuela Frontend"

Luego, abrimos nuestra terminal y corremos

# Le decimos a eslint que chequee el archivo main.js
npx eslint main.js

¡Vamos a ver que ese comando nos devuelve un error! Para ESLint, tener variables que no están siendo utilizadas es un error.

Ahora bien, como nuestro proyecto tiene un solo archivo, el comando de arriba funciona, pero ¿qué pasa si tenemos muchos cientos o miles de archivos? La mejor forma de solucionar esto es con un patrón que verifique todos los archivos *.js de nuestro proyecto.

npx eslint "**/*.js"

Esto debería devolver el mismo error que cuando ejecutamos el comando anterior. Ahora, cuando corramos el build de nuestra aplicación, Vite.js va a crear un directorio dist, y si utilizamos el patrón de arriba también vamos a correr ESLint contra los archivos en ese directorio, por eso, lo que debemos hacer es pasarle un flag para que ignore ese directorio, y todos los directorios que están incluídos en el archivo .gitignore

npx eslint "**/*.js" --ignore-pattern .gitignore

Otra forma de lograr esto, sería creando un archivo .eslintignore y poniendo los "paths" y archivos que queremos ignorar. En este caso, como queremos ignorar lo mismo que está en el archivo .gitignore, crear el archivo .eslintignore no es necesario.

El anterior comando funciona bien, pero es difícil de memorizar y muy largo de escribir. Para simplificar esto, vamos a crear un comando de NPM en nuestro package.json, abramos el archivo y agreguemos una línea dentro de la llave "scripts" así:

"lint": "eslint \"**/*.js\" --ignore-path .gitignore"

Ahora, solo tenemos que correr el siguiente comando para verificar nuestro código.

npm run lint

Configurar Prettier

¿Para qué sirve Prettier?

Prettier es una herramienta que nos sirve para estandarizar la forma en que se ve nuestro código. Por ejemplo, se puede encargar de agregar un ; después de cada línea donde sea necesario, de cambiar todas las comillas dobles por comillas simples, etc. Prettier es muy útil ya que nos permite tener un "codebase" homogéneo. ¡Ya quedaron atrás los PRs donde se sugerían cambios porque se estaba utilizando un " en vez de ' 🙂!

Instalar Prettier

Similar a ESLint, debemos installar Prettier como una devDependency. También debemos instalar la configuración de Prettier para ESLint para evitar conflictos entre ESLint y Prettier. Abramos el terminal y escribamos lo siguiente:

npm install prettier eslint-config-prettier --save-dev

Configurar Prettier en nuestro proyecto.

Para ver Prettier en acción, formateemos nuestro código de manera incorrecta, hagamos lo siguiente:

Ahora, abramos nuestra terminal, y escribamos el siguiente comando:

npx prettier main.js

Veremos que el resultado de esa operación es el código formateado correctamente

Sin embargo, nuestro archivo sigue viéndose igual. Para solucionar esto, corramos el mismo comando, pero con el flag --write para que Prettier se encargue de sobreescribir main.js

npx prettier main.js --write

Como hicimos con ESLint, es mejor hacer este comando en un script de NPM. Abramos nuestro package.json y agreguemos una nueva línea dentro de "scripts"

"prettier": "prettier \"**/*.js\" --write --ignore-path .gitignore"

Como pueden ver, prettier al igual que eslint, acepta el flag --ignore-path, lo que significa que podemos ignorar los mismos archivos y directorios que estén listados en el archivo .gitignore.

Ahora, cada vez que queramos formatear nuestros archivos .js, podemos correr el siguiente comando

npm run prettier

Por último, configuremos ESLint para que funcione correctamente con Prettier; ya que puede ser posible que nuestra configuración de Prettier tenga conflictos con nuestra configuración de ESLint. Por ejemplo, para ESLint puede ser un error que usemos ;, mientras que Prettier se va a encargar de agregar ; cuando sea necesario. Abramos nuestro .eslintrc.json y agreguemos lo siguiente:

"extends": [
"eslint:recommended",
"prettier"
],

Es muy importante que prettier sea la última regla dentro del array para que funcione correctamente.

Configurar Git Hooks con Husky

¿Para qué sirven los Git Hooks?

Los Git Hooks nos permiten ejecutar ciertas funciones o scripts cuando ocurre un evento de git en nuestras máquinas. Por ejemplo:

  • Quiero correr el chequeo de ESLint, antes de hacer commit
  • Quiero formatear mi código, antes de hacer push a Github

Los Git Hooks se pueden crear a mano, o a través de Husky. En este artículo, vamos a crear nuestros Git Hooks utilizando Husky.

Instalar Husky

Al igual que ESLint y Prettier, Husky debe ser instalado como un devDependency. Abramos nuestro terminal y escribamos:

npm install husky --save-dev

Configurar nuestros Git Hook

☝️ En este post estamos utilizando la versión más reciente de Husky, la versión 7.0. Una vez tengamos Husky instalado en nuestro proyecto, debemos correr el siguiente comando para que podamos agregar los git hooks que necesitemos.

npx husky install

Una vez configurado Husky, definamos qué comandos queremos asociar con nuestros git hooks:

  1. pre-commit Antes de hacer commit: Formatear nuestro código con prettier
  2. pre-push Antes de hacer push: Asegurarnos que no tenemos ningún error de eslint

☝️ La idea de tener Husky es de abortar el commit o el push si alguno de esos comandos falla.

Afortunadamente, ya tenemos esos dos comandos como scripts separados en nuestro package.json:

"lint": "eslint \"**/*.js\" --ignore-path .gitignore",
"prettier": "prettier \"**/*.js\" --write --ignore-path .gitignore"

Ahora, corramos los siguientes comandos para asociar los Git hooks a nuestros scripts de npm.

# `npm prettier` va a correr cada vez que queramos hacer un commit
npx husky add .husky/pre-commit "npm run prettier"# `npm lint` va a correr cada vez que queramos hacer push
npx husky add .husky/pre-push "npm run lint"

!🎉 Y eso es todo 🎉! Cuando queramos hacer un commit, prettier va a correr automáticamente y cuando queramos hacer push de nuestro código a nuestro control de versiones vamos a correr eslint automáticamente.

pre-commit

Ejecutamos prettier automáticamente antes de hacer commit

pre-push

Ejecutamos eslint antes de hacer push. En este caso, vemos que eslint nos arrojó un error porque no estamos utilizando la constante nombre. Para evitar que Husky ejecute los scripts, podemos utilizar el flag --no-verify de la siguiente manera

git commit -m 'Add git hooks' --no-verify

Ver commit - 46a97c

Configurar VSCode

Aunque tener npm scripts que se encargan de formatear y validar nuestro código es útil, sería aún mejor que pudieramos ver qué errores de eslint tenemos en nuestro editor (VSCode en este caso) además de poder formatear nuestros archivos con prettier automáticamente después de guardarlos. Afortunadamente, VSCode es el editor más popular del momento y tiene plugins para eslint y prettier. Instalemos la extensión de ESLint de Dirk Baeumer y Prettier de Prettier

Una vez instalemos la extensión de ESLint, vamos a ver que VSCode nos muestra todos los errores que tengamos en nuestro panel de Errores, además de subrayar las líneas afectadas.

Para decirle a VSCode que formatee nuestros archivos inmediatamente después de guardar, debemos activar la opción "Format on Save" en la configuración de VSCode y escoger Prettier como nuestro formateador por defecto.

Acá vemos como VSCode formatea nuestro código automáticamente después de guardar el archivo.

Algunos consejos

  • Hablando desde mi experiencia, siempre es bueno tener Git hooks. Al menos debemos configurar los dos hooks que menciono arriba (pre-commit y pre-push) con esto nos estamos asegurando que no vamos a enviar código "defectuoso" a nuestro control de versiones.
  • Si están utilizando un type checker como TypeScript, les recomendo no usar tsc en su pre-commit hook porque eso hace que TypeScript analice todo el proyecto y dependiendo del tamaño de su proyecto, esto puede demorarse varios segundos. En cambio, les sugiero usar tsc en su pre-push, esto es mejor porque la frecuencia con la que hacemos push es mucho menor comparada con la frecuencia de commits.
  • Si quieren correr npm scripts en paralelo, les recomiendo revisar npm-run-all
  • Siempre es bueno acompañar los Git hooks con lint-staged para solo correr prettier y eslint en los archivos que hayan cambiado desde el último commit.

Conclusión

El ecosistema de JavaScript es gigante, y tiene herramientas muy poderosas que pueden hacer nuestra vida mucho más fácil. Entre más responsabilidades podamos darle a la máquina, mucho mejor, eso nos da más tiempo para poder hacer lo que sabemos hacer, resolver problemas con código 🙂

¿Quieres mejorar tus habilidades de frontend?