28-09-2021 - Frontend

Come configurare ESLint e Prettier su Angular

Eccoci arrivati all'ultimo articolo della serie "Cose da fare prima di iniziare un progetto Angular".

Dopo aver visto Come ottenere il massimo dalla configurazione di Angular e Come equipaggiarsi prima di affrontare un progetto con i tools di Angular, in questa ultima parte parleremo di come migrare da TSLint a ESLint, come configurare ESLint e Prettier su un progetto Angular e come automatizzare, attraverso Husky, il processo di linting e formatting al pre-commit e al pre-push.

Che altro aspettiamo? LET'S COD... ehm volevo dire LET'S CONFIGURE!

 

Migrare da TSLint a ESLint

Con il rilascio di Angular 11 è stato annunciato che TSlint (deprecato nel 2019) è stato sostituito da ESLint ed esiste una soluzione di terze parti che consente di migrare facilmente da TSLint a ESLint attraverso l'utilizzo degli schematics.

 

Prima di eseguire il processo di migrazione occorre installare lo schematics convert-tslint-to-eslint. Per farlo basta lanciare il seguente comando all'interno della root del progetto Angular che si intende migrare:

1ng add @angular-eslint/schematics

​ Aggiunto lo schematics, successivamente occorre lanciare il processo di migrazione tramite il comando:

1ng g @angular-eslint/schematics:convert-tslint-to-eslint your_project_name

​ Il comando precedente analizzerà il file tslint.json e cercherà di far matchare le regole di TSLint con le regole di ESLint creando un nuovo file .eslintrc.json. Il comando si occuperà anche di eliminare il file tslint.json e rimuovere le dipendenze di tslint e codelyzer. Terminato il processo di migrazione (si consiglia di controllare eventuali errori di output presenti nel terminale) la vostra applicazione sarà pronta a utilizzare ESLint. ​

 

Configurare ESLint e Prettier

La vera potenza di ESLint risiede nelle sue possibilità di customizzazione.

Tramite il file .eslintrc.json è possibile utilizzare delle configurazioni "condivise" o impostare delle regole di linting personalizzate. Le regole, una volta impostate, ci consentiranno di visualizzare dei warning qualora il codice non rispetta le rules impostate.

Prima di dare un'occhiata al file di configurazione che personalmente raccomando in questo articolo, andiamo a terminare con l'installazione di Prettier, il quale si occuperà della formattazione del codice in base (indovinate un po') alle regole impostate all'interno del file .prettierrc.json.

 

Procediamo quindi con l'installazione di Prettier all'interno del progetto:

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

​ Questo comando, oltre a installare Prettier, si occupa anche dell'installazione di due package che disabilitano alcune regole di ESLint per evitare che ci siano conflitti con Prettier. Una volta terminata l'installazione, siamo pronti a configurare le regole di linting e formattazione. Creare all'interno della root di progetto il file .prettierrc.json con all'interno la seguente configurazione:

1{
2  "singleQuote": true,
3  "trailingComma": "none",
4  "endOfLine": "auto"
5}

​ Qualora si desideri configurare diversamente Prettier, si rimanda alla lista delle opzioni disponibili. ​ ​ 

Terminata la configurazione di Prettier, passiamo adesso a configurare ESLint creando all'interno della root di progetto il file .eslintrc.json con la seguente configurazione:

1{
2  "root": true,
3  "ignorePatterns": [
4    "projects/**/*"
5  ],
6  "overrides": [
7    {
8      "files": [
9        "*.ts"
10      ],
11      "parserOptions": {
12        "project": [
13          "tsconfig.json",
14          "e2e/tsconfig.json"
15        ],
16        "createDefaultProgram": true
17      },
18      "extends": [
19        "eslint:recommended",
20        "plugin:@angular-eslint/recommended",
21        "plugin:@angular-eslint/template/process-inline-templates",
22        "plugin:prettier/recommended"
23      ],
24      "rules": {
25        "@angular-eslint/component-selector": [
26          "error",
27          {
28            "prefix": "app",
29            "style": "kebab-case",
30            "type": "element"
31          }
32        ],
33        "@angular-eslint/directive-selector": [
34          "error",
35          {
36            "prefix": "app",
37            "style": "camelCase",
38            "type": "attribute"
39          }
40        ],
41        "sort-imports": [
42          "error",
43          {
44            "ignoreCase": false,
45            "ignoreDeclarationSort": false,
46            "ignoreMemberSort": false,
47            "memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
48            "allowSeparatedGroups": false
49          }
50        ]
51      }
52    },
53    {
54      "files": [
55        "*.html"
56      ],
57      "extends": [
58        "plugin:@angular-eslint/template/recommended"
59      ],
60      "rules": {}
61    }
62  ]
63}

​ ​ 

Le parti che vorrei attenzionare sono: extends e rules.

Nel primo sono dichiarate le regole "condivise" grazie all'installazione dei package di terze parti, nel secondo, invece, sono riportate le regole custom.

L'unica regola che mi sono sentito in dovere di aggiungere alla lista è sort-imports, la quale fa emettere un errore in fase di compilazione qualora i moduli ES6 importati non sono ordinati correttamente. Da notare come l'ordine di dichiarazione della lista dei plugins e delle regole è importante. Qui una lista completa delle regole di configurazione ESLint.

Infine, se si desidera ignorare il linting di alcuni file, creare all'interno della root di progetto il file .eslintignore:

1package.json
2package-lock.json
3dist
4e2e/**
5karma.conf.js
6commitlint.config.js

​ Prima di concludere, andiamo ad aggiungere all'interno del package.json gli script per eseguire da linea di comando il linting e la formattazione del codice:

1...
2"scripts": {
3    "ng": "ng",
4    "start": "ng serve",
5    "build": "ng build",
6    "test": "ng test",
7    "lint": "npx eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
8    "format": "npx prettier 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --write",
9    "e2e": "ng e2e"
10  }
11...

Et voilà! Abbiamo terminato con l'installazione e configurazione di ESLint e Prettier. ​

 

Configurare Husky

Eccoci giunti all'ultima parte dell'articolo: come possiamo automatizzare il processo di linting e formattazione prima di inviare le modifiche al repository remoto?

Semplicemente utilizzando Husky, il quale, attraverso gli hook di Git, consente di eseguire dei comandi in fase di pre-commit.

Per configurare il processo di linting e formattazione automatico al pre-commit, occorre prima installare lint-staged:

1npx [email protected]2 lint-staged

​ Una volta eseguito il comando, verrà creata la cartella .husky all'interno della root di progetto. Aprendo questa cartella vi trovere il file .pre-commit. Aprite il file e modificatelo in questa maniera:

1#!/bin/sh
2. "$(dirname "$0")/_/husky.sh"
34npx lint-staged -c .lintstagedrc.js

​ In questo modo stiamo andando a specificare a lint-staged il file di configurazione per automatizzare il processo di linting e formattazione. A questo punto non rimane altro che creare all'interno della root di progetto il file .lintstagedrc.js:

1const { ESLint } = require('eslint')
23const removeIgnoredFiles = async (files) => {
4  const eslint = new ESLint()
5  const isIgnored = await Promise.all(
6    files.map((file) => {
7      return eslint.isPathIgnored(file)
8    })
9  )
10  const filteredFiles = files.filter((_, i) => !isIgnored[i])
11  return filteredFiles.join(' ')
12}
1314module.exports = {
15  'src/**/*.{js,jsx,ts,tsx,html,css,scss}': async (files) => {
16    const filesToLint = await removeIgnoredFiles(files)
17    return [`npx prettier --write ${filesToLint}`, `npx eslint ${filesToLint}`]
18  },
19}

​ Questo file è necessario per indicare a lint-staged di ignorare i file specificati all'interno di .eslintignore. Finalmente, dopo tanta fatica, abbiamo concluso con le configurazioni e possiamo testare che tutto funzioni correttamente. Aprendo il terminale e lanciando i comandi

1npm run format && npm run lint

​ avrete la possibilità di lanciare gli script di formattazione e linting.

In più, se avete quel collega antipatico che si dimentica di lanciare questi comandi prima di ogni commit, avete gli alleati Husky e Lint Staged che, prontamente, verificheranno che i file siano formattati e lintati correttamente, bloccando il tentativo di commit qualora non lo fossero.

 

Conclusioni

Eccoci giunti all'ultima parte della serie "Cose da fare prima di iniziare un progetto Angular". Abbiamo visto e imparato insieme quali sono gli strumenti e le pratiche che personalmente adotto prima di iniziare un qualsiasi progetto Angular.

Nel prossimo articolo parlerò di un argomento che mi sta molto a cuore e che nelle ultime settimane mi ha permesso di imparare molto su questo framework e non solo. Andremo, infatti, a parlare di Domain-driven Design e Front-end e di come è possibile utilizzare alcuni aspetti dell'approccio DDD anche in questo ambito.

Autore

Mirko Rapisarda

Developer @Devmy, PUG Catania Organizer

Da sempre considera programmare più come una passione che come un lavoro. D'altra parte, questa è la ragione principale che spinge i programmatori a imparare nuovi linguaggi, nuove tecnologie e metodologie ogni giorno. Senza questa "fame" di sapere non è possibile raggiungere grandi conquiste in questa professione.

La sua passione lo ha portato allo sviluppo di applicazioni web usando tecnologie quali PHP, MySQL, Symfony, JavaScript, Node, Angular, tuttavia sperimenta volentieri anche con altri linguaggi e tecnologie come Vue, VB e Flutter. Grande sostenitore della metodologia Agile e dei principi presenti all'interno del manifesto che lo hanno fortemente ispirato nella creazione di una serie di libri che ben esprimono i vantaggi di seguire questi principi.

Precedentemente docente presso PED Academy.

.Devmy su linkedin

Contattaci

Sei interessato a sviluppare un'applicazione in Angular?

Anche se - semplicemente - vuoi prendere un caffè con noi o vedere la nostra collezione di Action Figures scrivici tramite questo form.

Questo sito è protetto da reCAPTCHA e si applicano le Norme sulla privacy e i Termini di servizio di Google.