Introducción

¿Cuántas veces has entrado en discusiones con tu equipo sobre si usar comillas simples o dobles en tu código TypeScript? ¿O sobre la indentación en los templates HTML de tus componentes Angular? ¿O si el punto y coma al final de la línea es realmente necesario? Estas «guerras de estilo», aunque parezcan menores, consumen tiempo y energía en el desarrollo de aplicaciones Angular, y pueden llevar a inconsistencias en el código base que dificultan la lectura y el mantenimiento.

En mis artículos anteriores, exploramos cómo Husky nos ayuda a automatizar tareas en nuestros commits de Git y cómo ESLint (junto a sus plugins específicos) vigila la calidad y los posibles errores de nuestro código, especialmente en el ecosistema TypeScript de Angular. Hoy, vamos a profundizar en la tercera pieza clave de este rompecabezas para un desarrollo Angular moderno y eficiente: Prettier.

Aunque ya lo mencionamos, en este artículo nos sumergiremos en qué hace a Prettier tan especial, cómo configurarlo a fondo y, lo más importante, cómo integrarlo perfectamente con las herramientas de linting de Angular (@angular-eslint) y Husky para crear un flujo de trabajo donde el formato del código deja de ser una preocupación. ¡Prepárate para decirle adiós al formateo manual y a las discusiones de estilo en tus proyectos Angular!

¿Qué es exactamente Prettier y por qué deberías usarlo? (Más allá de lo básico)

Prettier se autodefine como un formateador de código opinionado. ¿Qué significa esto?

  • Formateador de Código: Su única misión es tomar tu código fuente (TypeScriptHTMLCSS/SCSSJSON, etc.) y reescribirlo siguiendo un conjunto de reglas de estilo consistentes. Se encarga de saltos de línea, espaciado, comillas, puntos y comas, paréntesis, etc.
  • Opinionado: Aquí está la clave. Prettier no intenta ser infinitamente configurable. Implementa un estilo de código bastante específico y ofrece solo un número limitado de opciones para modificarlo.

La filosofía «Opinionada»: ¿Una ventaja?

¡Absolutamente! En el contexto de Angular, donde trabajamos con TypeScript y plantillas HTML complejas, la naturaleza opinionada de Prettier es una gran fortaleza:

  1. Elimina Discusiones: Al adoptar Prettier, el equipo acepta su estilo tanto para TS como para HTML. Se acabaron los debates sobre tabuladores vs. espacios o la posición de los brackets en las plantillas.
  2. Consistencia Total: Garantiza que todo el código del proyecto (componentesserviciosmódulosplantillasestilos) tenga exactamente el mismo formato. Esto mejora drásticamente la legibilidad.
  3. Menos Configuración de Formato: No tienes que perder tiempo definiendo cientos de reglas de formato en ESLint. Instalas Prettier, ajustas unas pocas opciones clave, y dejas que él se encargue del cómo se ve el código.
  4. Facilita la Adopción: Es más fácil para los nuevos miembros del equipo adaptarse al estilo del proyecto Angular: es automático.

La diferencia crucial con @angular-eslint

Es fundamental entender la división de responsabilidades:

  • @angular-eslint (y @typescript-eslint): Se centra en la calidad del código, la detección de errores y el cumplimiento de las buenas prácticas específicas de Angular y TypeScript. Busca patrones problemáticos (uso incorrecto de decoradores, ciclos de vida, RxJS), variables no usadas, lógica compleja, etc. Puede tener reglas de formato, pero gestionarlas es tedioso y propenso a conflictos con Prettier.
  • Prettier: Se centra exclusivamente en el formato del código (TSHTMLCSS/SCSS, etc.). No le importa la lógica, solo la presentación visual consistente.

La conclusión es clara: No son competidores, son compañeros. La mejor práctica moderna en Angular es usar @angular-eslint para la calidad y las reglas específicas del framework, y Prettier para el formato, configurándolos para que trabajen juntos.

Instalación y configuración «A fondo»

1. Instalación:

Añade Prettier como dependencia de desarrollo. Es muy recomendable usar la opción --save-exact (o equivalente en Yarn) para evitar que actualizaciones menores automáticas cambien sutilmente el formato y generen ruido en los commits.

# Usando npm
npm install --save-dev --save-exact prettier

# Usando yarn
yarn add --dev --exact prettier

2. Archivo de configuración (.prettierrc):

Prettier buscará un archivo de configuración en la raíz de tu proyecto. Puedes usar varios formatos, pero .prettierrc.json (o simplemente .prettierrc con JSON dentro) es común y fácil de entender:

# Crea el archivo (ejemplo con JSON)
touch .prettierrc.json

Ahora, exploremos algunas de las opciones de configuración más importantes donde puedes «profundizar»:

  • printWidth (default: 80): Longitud máxima de línea. Prettier intentará romper las líneas que excedan este límite. Un valor común hoy en día podría ser 100 o 120.
  • tabWidth (default: 2): Número de espacios por nivel de indentación.
  • useTabs (default: false): Si es true, usa tabuladores en lugar de espacios para la indentación.
  • semi (default: true): Añade punto y coma al final de las sentencias. Si lo pones a false, los quitará donde sea seguro hacerlo.
  • singleQuote (default: false): Si es true, usa comillas simples en lugar de dobles para los strings (excepto en JSX por defecto).
  • quoteProps (default: "as-needed"): Cuándo añadir comillas a las propiedades de los objetos. "consistent" (si una propiedad necesita comillas, todas las tendrán) o "preserve" (respeta la entrada) son otras opciones.
  • jsxSingleQuote (default: false): Si es true, usa comillas simples en JSX.
  • trailingComma (default: "es5"): Añade comas al final en arrays y objetos multi-línea donde sea válido en ES5. "all" lo hace también en parámetros de función. "none" las quita. Usar "es5" o "all" es genial para los diffs de Git, ya que añadir un nuevo elemento solo cambia una línea.
  • bracketSpacing (default: true): Imprime espacios entre las llaves en objetos literales: { foo: bar } vs {foo: bar}.
  • bracketSameLine (default: false): Si es true, coloca el > de cierre de una etiqueta HTML/JSX/Vue multi-línea al final de la última línea, en lugar de en una línea nueva. (jsxBracketSameLine está obsoleto).
  • arrowParens (default: "always"): Añade paréntesis alrededor de un único parámetro en funciones flecha. "avoid" los quita: x => x vs (x) => x.
  • endOfLine (default: "lf"): Controla los finales de línea. "lf" (Linux/macOS), "crlf" (Windows), "cr" (raro), "auto" (mantiene los existentes). Es importante para equipos que trabajan en diferentes sistemas operativos; "lf" suele ser la opción más segura y estándar con Git.
  • Importante para HTML: Prettier también formateará tus archivos .html. Las opciones como printWidthtabWidthbracketSameLine afectan directamente cómo se ven tus plantillas.

Ejemplo de .prettierrc.json:

{
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true, // Preferencia común en la comunidad TS/Angular
  "trailingComma": "es5",
  "bracketSpacing": true,
  "bracketSameLine": false, // Pone el ">" en nueva línea en HTML
  "arrowParens": "always",
  "endOfLine": "lf"
  // Prettier detecta automáticamente los parsers para TS y HTML
}

Recuerda: La idea de Prettier es minimizar la configuración. Empieza con los valores por defecto y ajusta solo aquello con lo que tu equipo realmente no esté de acuerdo o necesite cambiar por alguna razón específica.

3. Ignorando código (.prettierignore):

Al igual que .gitignore, puedes crear un archivo .prettierignore para decirle a Prettier qué archivos o carpetas no debe formatear. Es útil para node_modules, carpetas de build (dist, build, coverage), archivos generados automáticamente, o quizás archivos de configuración muy específicos.

Ejemplo de .prettierignore:

# Ignorar dependencias y archivos de build
node_modules
dist
build
coverage
.angular/cache

# Ignorar archivos específicos
src/legacy/problematic-file.js
src/assets/generated-data.json

# Ignorar todos los archivos de un tipo en una carpeta específica
src/generated/**/*.svg

También puedes ignorar bloques específicos de código dentro de un archivo usando un comentario // prettier-ignore en TypeScript o <!– prettier-ignore –> en HTML, justo antes del bloque. Úsalo con moderación, solo cuando el formato automático realmente rompa algo o sea muy poco legible para un caso muy particular.

// prettier-ignore
matrix = [
  1, 0, 0,
  0, 1, 0,
  0, 0, 1
];

Ejecutando Prettier eficazmente

1. Desde la Línea de Comandos (CLI):
  • Comprobar formato: Útil en CI (Integración Continua) o para verificar antes de un commit.
# Comprueba todos los archivos soportados en el proyecto
npx prettier --check .
# O específicamente TS y HTML en src/
npx prettier --check "src/**/*.{ts,html}"
  • Formatear archivos: Reescribe los archivos aplicando el formato.
# Formatea todo
npx prettier --write .
# O específicamente TS y HTML en src/
npx prettier --write "src/**/*.{ts,html}"
2. Scripts en package.json:

Es una buena práctica añadir scripts para facilitar la ejecución:

// package.json
"scripts": {
  // ... otros scripts (ng serve, ng build...)
  "format": "prettier --write \"./src/**/*.{ts,html,scss,json,md}\"", // Ajusta patrones según necesites
  "check-format": "prettier --check \"./src/**/*.{ts,html,scss,json,md}\""
}

Ahora puedes ejecutar npm run format o npm run check-format.

3. Integración con el Editor (¡La Magia Sucede Aquí!)

Esta es la forma más cómoda de usar Prettier en el día a día. Casi todos los editores modernos (VS Code, WebStorm, Sublime Text, etc.) tienen extensiones para Prettier.

  • Instala la Extensión: Busca «Prettier» en el marketplace de tu editor (ej. «Prettier – Code formatter» para VS Code).
  • Configura «Format on Save»: La opción más popular es configurar tu editor para que formatee automáticamente el archivo cada vez que lo guardas. En VS Code, esto se hace en la configuración (JSON o UI):
// settings.json (VS Code)
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode", // Asegúrate que sea el default
  // Aplica Format on Save para los lenguajes de Angular
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": { // Para los templates de Angular
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": { // Si usas SCSS
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  // etc. para json, md...
}
  • Usa la Versión del Proyecto: Asegúrate de que la extensión de tu editor esté configurada para usar la versión de Prettier instalada en tu proyecto (node_modules/prettier) en lugar de una versión global. Esto garantiza que todo el equipo use exactamente la misma versión y reglas. La mayoría de las extensiones lo hacen por defecto hoy en día.

Con «Format on Save«, Prettier se vuelve casi invisible. Simplemente escribes tu código y al guardar… ¡Puf! Se formatea automáticamente.

La integración perfecta: Prettier + ESLint + Husky (Poniéndolo todo junto)

Aquí es donde conectamos todo para un flujo de trabajo robusto en Angular. El objetivo es asegurar que ESLint (configurado con @angular-eslint) maneje la calidad del código y las reglas específicas de Angular/TypeScript, mientras que Prettier se encarga exclusivamente del formato, y Husky automatiza la verificación antes de cada commit.

1. Prettier con @angular-eslint:

Necesitamos que ESLint no interfiera con las reglas de formato de Prettier.

  • Instala las dependencias necesarias (si no las tienes): Asegúrate de tener instalados los paquetes clave como eslint@typescript-eslint/parser@typescript-eslint/eslint-plugin@angular-eslint/eslint-plugin@angular-eslint/template-parser@angular-eslint/eslint-plugin-template. Para la integración con Prettier, necesitarás eslint-config-prettier (para desactivar reglas conflictivas) y opcionalmente eslint-plugin-prettier (para reportar diferencias de formato como errores de ESLint).
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin @angular-eslint/eslint-plugin @angular-eslint/template-parser @angular-eslint/eslint-plugin-template eslint-config-prettier eslint-plugin-prettier
# O usando ng add @angular-eslint/schematics si empiezas de cero y luego añadiendo las de prettier
  • Configura .eslintrc.json: La clave es usar eslint-config-prettier para desactivar reglas conflictivas y opcionalmente eslint-plugin-prettier para integrar el chequeo. La estructura típica en Angular usa overrides para separar la configuración de TypeScript y HTML:
// .eslintrc.json
{
  "root": true,
  "ignorePatterns": ["projects/**/*"], // Ajusta según tu estructura (mono-repo o no)
  "plugins": [ // Añade 'prettier' aquí si usas eslint-plugin-prettier
    "prettier"
  ],
  "overrides": [
    {
      // Configuración para archivos TypeScript (*.ts)
      "files": ["*.ts"],
      "parser": "@typescript-eslint/parser",
      "parserOptions": {
        "project": ["tsconfig.json"], // Asegúrate que apunte a tu tsconfig
        "createDefaultProgram": true
      },
      "plugins": [
        "@typescript-eslint",
        "@angular-eslint"
        // 'prettier' se añade globalmente si se usa el plugin
      ],
      "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",   // Reglas TS base
        "plugin:@angular-eslint/recommended",    // Reglas Angular para TS
        // ¡MUY IMPORTANTE! Poner al final para desactivar conflictos:
        "prettier" // Usa eslint-config-prettier
      ],
      "rules": {
        // Reglas específicas de Angular o TS que quieras añadir/modificar
        "@angular-eslint/directive-selector": ["error", { "type": "attribute", "prefix": "app", "style": "camelCase" }],
        "@angular-eslint/component-selector": ["error", { "type": "element", "prefix": "app", "style": "kebab-case" }],
        // Si usas eslint-plugin-prettier, añade esta regla:
        "prettier/prettier": "error" // Reporta diferencias de Prettier como errores ESLint
      }
    },
    {
      // Configuración para archivos de Plantilla (*.html)
      "files": ["*.html"],
      "parser": "@angular-eslint/template-parser",
      "plugins": [
        "@angular-eslint/template"
      ],
      "extends": [
        "plugin:@angular-eslint/template/recommended", // Reglas Angular para HTML
        "plugin:@angular-eslint/template/accessibility" // Opcional: Reglas de accesibilidad
        // Nota: Prettier formatea HTML directamente. No se suele poner 'prettier' aquí
        // en 'extends', ya que eslint-config-prettier se aplica globalmente
        // y afecta principalmente a reglas TS/JS que podrían chocar.
      ],
      "rules": {
        // Puedes añadir/sobrescribir reglas específicas de plantilla aquí
        // Si quieres reportar formato Prettier en HTML vía ESLint (menos común):
        // "prettier/prettier": ["error", { "parser": "angular" }]
      }
    }
  ]
}
  • eslint-config-prettier (incluido al poner «prettier» en extends al final de la sección TS) desactiva reglas de ESLint/@angular-eslint que chocan con Prettier.
  • eslint-plugin-prettier (si lo añades a plugins globalmente y configuras la regla «prettier/prettier»: «error» en la sección TS) hace que las diferencias de formato en archivos TypeScript se reporten como errores de ESLint, visibles en el editor y al ejecutar eslint.

2. Prettier con Husky (y lint-staged):

Asegura que solo código bien formateado y sin errores de lint llegue a tu repositorio Git.

  • Instala lint-staged:npm install --save-dev lint-stagedcontent_copydownloadUse code with caution.Bash
npm install --save-dev lint-staged
  • Configura lint-staged en package.json:
    Define qué comandos ejecutar sobre los archivos que están en el staging area de Git (.ts.html.scss, etc.).
// package.json
"lint-staged": {
  // Para archivos TypeScript y HTML
  "*.{ts,html}": [
    "eslint --fix",       // Primero arregla lo que ESLint pueda (incluyendo formato si usas el plugin)
    "prettier --write"    // Asegura el formato final con Prettier (importante si ESLint no lo cubre todo)
  ],
  // Para otros archivos (SCSS, JSON, Markdown...) que Prettier soporte
  "*.{scss,css,json,md}": [
    "prettier --write"
  ]
}

(El orden eslint –fix / prettier –write puede necesitar ajustes según tu configuración exacta. Ejecutar ambos suele ser una estrategia segura para cubrir todos los casos. prettier –write asegura que el formato final sea el de Prettier, incluso si ESLint no lo aplicó completamente).

  • Configura el Hook pre-commit de Husky:

Asegúrate de que tu script en .husky/pre-commit ejecute lint-staged.

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

(Y asegúrate de que el archivo tenga permisos de ejecución: chmod +x .husky/pre-commit).

El flujo completo en Angular:

Ahora, cuando un desarrollador en tu equipo haga git add <archivos> y luego git commit -m «mensaje», ocurrirá lo siguiente de forma automática:

  1. Husky intercepta el commit y ejecuta el script pre-commit.
  2. El script pre-commit lanza npx lint-staged.
  3. lint-staged identifica los archivos modificados en el staging area que coincidan con los patrones configurados (.ts.html.scss…).
  4. Ejecuta los comandos asociados (eslint –fixprettier –writesolo sobre esos archivos modificados.
  5. Si los comandos tienen éxito (formatean y/o arreglan errores sin fallar), lint-staged terminará con éxito. Los archivos potencialmente modificados por los comandos se incluirán automáticamente en el commit.
  6. Si lint-staged tiene éxito, el commit se completará con los archivos limpios y formateados.
  7. Si alguno de los comandos falla (p.ej., ESLint encuentra un error grave que no puede arreglar automáticamente), lint-staged fallará, el script pre-commit fallará, y el commit será abortado, mostrando el error al desarrollador para que lo corrija antes de intentar commitear de nuevo.

¡Magia! Tienes un sistema robusto y automático que garantiza que todo el código que entra en tu repositorio Angular está correctamente formateado según Prettier y cumple con las reglas de calidad definidas en @angular-eslint.

Conclusión

Prettier es mucho más que un simple formateador; es una herramienta esencial en el desarrollo moderno de Angular. Trae consistencia automática al formato de tu código TypeScriptHTML y CSS/SCSSreduce la fricción del equipo eliminando debates de estilo, y libera tiempo mental al quitarte la preocupación del formato manual.

Cuando se combina con las potentes reglas de calidad de @angular-eslint y la automatización de Husky + lint-staged, formas un trío imbatible que eleva la calidad, la legibilidad y la mantenibilidad de tus proyectos Angular. Te permite a ti y a tu equipo centraros en lo que realmente importa: construir funcionalidades increíbles para tus aplicaciones, sabiendo que la base de código se mantiene limpia y consistente de forma automática.

Si aún no has integrado Prettier en tu flujo de trabajo Angular, ¡ahora es el momento perfecto para hacerlo! La inversión inicial en configuración se paga con creces en tranquilidad y eficiencia a largo plazo.

Llamada a la acción (CTA)

¿Y tú? ¿Ya usas Prettier en tus proyectos Angular? ¿Qué configuración de @angular-eslint y Prettier te funciona mejor? ¿Has tenido algún reto específico en la integración con Husky o lint-staged? ¡Comparte tu experiencia y tus consejos en los comentarios!

Y si te perdiste los artículos anteriores sobre las otras herramientas clave de este flujo de trabajo: