Linting JavaScript

Il linting è il processo di analisi statica del codice per identificare errori di sintassi, problemi di stile, pattern problematici e potenziali bug prima dell’esecuzione. In JavaScript, dove la flessibilità del linguaggio può portare a codice inconsistente e propenso agli errori, il linting diventa uno strumento essenziale per mantenere qualità e leggibilità del codice.
Perché il Linting è Fondamentale
JavaScript è un linguaggio dinamico e permissivo che consente molte libertà sintattiche. Questa flessibilità, pur essendo una forza, può diventare un problema quando si lavora in team o su progetti di grandi dimensioni. Il linting risolve problemi comuni come variabili non dichiarate, codice morto, inconsistenze stilistiche e pattern che possono causare bug sottili.
Un linter non si limita a controllare la sintassi: analizza il codice per pattern anti-pattern, suggerisce best practices moderne, identifica potenziali problemi di performance e può anche enformare convenzioni di naming e organizzazione del codice. È come avere un mentore esperto che rivede costantemente il tuo codice.
ESLint: Lo Standard de Facto
ESLint è il linter JavaScript più diffuso e potente. A differenza dei suoi predecessori, ESLint è completamente configurabile e estensibile, permettendo di creare regole personalizzate per adattarsi alle esigenze specifiche di ogni progetto o organizzazione.
Installazione e Setup Base
# Installazione globale
npm install -g eslint
# Installazione per progetto (consigliata)
npm install --save-dev eslint
# Inizializzazione configurazione interattiva
npx eslint --init
L’inizializzazione interattiva ti guida attraverso domande sullo stile di codice preferito, framework utilizzati e ambiente di sviluppo, generando automaticamente una configurazione appropriata.
Configurazione Fondamentale
// .eslintrc.js
module.exports = {
// Ambiente di esecuzione
env: {
browser: true,
es2021: true,
node: true,
jest: true,
},
// Estensioni di configurazioni predefinite
extends: [
"eslint:recommended",
"@typescript-eslint/recommended",
"prettier", // Deve essere ultimo per evitare conflitti
],
// Parser per sintassi moderna
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2021,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
// Plugin aggiuntivi
plugins: ["@typescript-eslint", "react", "react-hooks", "import"],
// Regole personalizzate
rules: {
// Errori che bloccano il build
"no-unused-vars": "error",
"no-undef": "error",
"no-console": "warn",
// Stile e best practices
"prefer-const": "error",
"no-var": "error",
eqeqeq: ["error", "always"],
// Regole React specifiche
"react/prop-types": "warn",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
},
// Configurazioni specifiche per file
overrides: [
{
files: ["**/*.test.js", "**/*.spec.js"],
rules: {
"no-console": "off", // Permetti console.log nei test
},
},
],
};
Regole Essenziali e Configurazioni
Categorie di Regole
Possibili Errori: Identificano codice che potrebbe causare errori runtime o comportamenti inaspettati.
// Esempi di regole per possibili errori
{
'no-unused-vars': 'error', // Variabili dichiarate ma non usate
'no-undef': 'error', // Uso di variabili non dichiarate
'no-unreachable': 'error', // Codice irraggiungibile
'no-constant-condition': 'error', // Condizioni sempre vere/false
'no-dupe-keys': 'error', // Chiavi duplicate negli oggetti
'no-empty': 'warn', // Blocchi vuoti
'valid-typeof': 'error' // Operatori typeof incorretti
}
Best Practices: Enforchano pattern di codice che prevengono bug e migliorano la leggibilità.
{
'eqeqeq': ['error', 'always'], // Usa sempre === invece di ==
'no-eval': 'error', // Vieta uso di eval()
'no-implied-globals': 'error', // Previeni variabili globali accidentali
'prefer-const': 'error', // Usa const quando possibile
'no-var': 'error', // Vieta var, usa let/const
'curly': ['error', 'all'], // Require parentesi graffe sempre
'default-case': 'warn' // Require default in switch
}
Stile e Formattazione: Mantengono consistenza visuale nel codice.
{
'indent': ['error', 2], // Indentazione a 2 spazi
'quotes': ['error', 'single'], // Usa virgolette singole
'semi': ['error', 'always'], // Richiedi semicoloni
'comma-dangle': ['error', 'never'], // No virgole finali
'object-curly-spacing': ['error', 'always'], // Spazi nelle parentesi graffe
'array-bracket-spacing': ['error', 'never'] // No spazi nelle parentesi quadre
}
Integrazione con Prettier
Prettier è un code formatter che si occupa automaticamente della formattazione, mentre ESLint si concentra sulla qualità del codice. La combinazione dei due è potentissima:
# Installazione
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
# .prettierrc
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false
}
// .eslintrc.js con integrazione Prettier
module.exports = {
extends: [
"eslint:recommended",
"prettier", // Disabilita regole di stile di ESLint che confliggono
],
plugins: ["prettier"],
rules: {
"prettier/prettier": "error", // Tratta errori Prettier come errori ESLint
},
};
Configurazioni Predefinite Popolari
Airbnb Style Guide
Una delle configurazioni più rispettate della community:
npm install --save-dev eslint-config-airbnb
# .eslintrc.js
module.exports = {
extends: ['airbnb'],
rules: {
// Override specifiche se necessario
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }]
}
};
Standard JS
Configurazione minimalista senza semicoloni:
npm install --save-dev eslint-config-standard
# .eslintrc.js
module.exports = {
extends: ['standard']
};
Integrazione nel Workflow
Script NPM
{
"scripts": {
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"lint:watch": "nodemon --exec 'npm run lint' --watch src/",
"precommit": "npm run lint"
}
}
Git Hooks con Husky
npm install --save-dev husky lint-staged
# package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"git add"
]
}
}
Editor Integration
La maggior parte degli editor moderni supporta ESLint nativamente:
// VS Code settings.json
{
"eslint.enable": true,
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
]
}
Regole Personalizzate
Per esigenze specifiche, puoi creare regole personalizzate:
// eslint-plugin-custom/rules/no-hardcoded-colors.js
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow hardcoded color values",
category: "Best Practices",
},
fixable: null,
schema: [],
},
create(context) {
const colorRegex = /#[0-9a-fA-F]{3,6}\b/;
return {
Literal(node) {
if (typeof node.value === "string" && colorRegex.test(node.value)) {
context.report({
node,
message:
"Avoid hardcoded color values. Use CSS variables or theme constants.",
});
}
},
};
},
};
// Utilizzo
// .eslintrc.js
module.exports = {
plugins: ["custom"],
rules: {
"custom/no-hardcoded-colors": "warn",
},
};
Gestione di Progetti Grandi
Configurazioni Multiple
Per progetti complessi, puoi avere configurazioni diverse per diverse parti:
// .eslintrc.js (root)
module.exports = {
extends: ["eslint:recommended"],
overrides: [
{
files: ["src/components/**/*.js"],
extends: ["airbnb/react"],
},
{
files: ["src/utils/**/*.js"],
rules: {
"no-console": "off",
},
},
{
files: ["**/*.test.js"],
env: {
jest: true,
},
rules: {
"no-unused-expressions": "off",
},
},
],
};
Performance e Esclusioni
// .eslintignore
node_modules/
dist/
build/
*.min.js
coverage/
// .eslintrc.js
module.exports = {
ignorePatterns: [
'src/legacy/**',
'src/vendor/**'
]
};
Best Practices per il Linting
Introduzione Graduale: In progetti esistenti, introduci il linting gradualmente, iniziando con regole di errore base e aggiungendo regole di stile progressivamente.
Consenso del Team: Le regole di linting dovrebbero essere discusse e accettate dal team. Un linter troppo rigido può rallentare lo sviluppo, mentre uno troppo permissivo perde efficacia.
Automazione: Integra il linting nei processi automatici (CI/CD, pre-commit hooks) per garantire che venga sempre eseguito.
Documentazione: Documenta le regole personalizzate e le ragioni dietro scelte specifiche per aiutare nuovi membri del team.
Aggiornamenti Regolari: Mantieni ESLint e le sue configurazioni aggiornate per beneficiare di nuove regole e miglioramenti.
Il linting non è solo uno strumento tecnico, ma un investimento nella qualità a lungo termine del codice. Un setup di linting ben configurato riduce significativamente i bug, migliora la leggibilità del codice e facilita la collaborazione nel team, diventando un moltiplicatore di produttività per l’intero processo di sviluppo.
