Come Debuggare JavaScript nel Browser: Guida Chrome DevTools

THEJORD Team1 min di lettura
javascriptdebugchromesviluppo

Come debuggare JavaScript nel browser con Chrome DevTools: breakpoints, console, network panel. Guida completa per trovare e risolvere bug efficacemente.

Come Debuggare JavaScript nel Browser: Guida Chrome DevTools

Introduzione al Debug JavaScript

Il debug è un'arte fondamentale per ogni sviluppatore. Chrome DevTools offre strumenti potenti per ispezionare, debuggare e profilare applicazioni JavaScript. Padroneggiare questi strumenti può ridurre drasticamente il tempo speso a cercare bug. Questa guida copre tecniche essenziali e avanzate per il debugging efficace.

Aprire DevTools

# Scorciatoie per aprire DevTools

Windows/Linux:
F12                    → Apri DevTools
Ctrl+Shift+I           → Apri DevTools
Ctrl+Shift+J           → Apri Console
Ctrl+Shift+C           → Inspect element

macOS:
Cmd+Option+I           → Apri DevTools
Cmd+Option+J           → Apri Console
Cmd+Shift+C            → Inspect element

# Click destro su qualsiasi elemento → "Inspect"

Console

Metodi Console Essenziali

// Log base
console.log('Messaggio normale');
console.info('Informazione');
console.warn('Warning');
console.error('Errore');
console.debug('Debug (nascosto di default)');

// Log con stile
console.log('%cTesto rosso grande', 'color: red; font-size: 20px');
console.log('%cSuccesso%c e %cErrore', 'color: green', '', 'color: red');

// Formattazione
console.log('Utente: %s, ID: %d', 'Mario', 123);
console.log('Oggetto: %o', { nome: 'Mario' });

// Oggetti e array
console.table([
  { nome: 'Mario', età: 30 },
  { nome: 'Luigi', età: 28 }
]);

console.dir(document.body);  // Esplora proprietà DOM

// Gruppi
console.group('Operazioni utente');
console.log('Login');
console.log('Fetch dati');
console.groupEnd();

// Gruppi collassati
console.groupCollapsed('Dettagli');
console.log('Info nascosta di default');
console.groupEnd();

Performance e Debug

// Timer per misurare performance
console.time('operazione');
// ... codice da misurare ...
console.timeEnd('operazione'); // operazione: 123.45ms

// Timer con checkpoint
console.time('processo');
console.timeLog('processo', 'Fase 1 completata');
console.timeLog('processo', 'Fase 2 completata');
console.timeEnd('processo');

// Conteggio chiamate
function handleClick() {
  console.count('click'); // click: 1, click: 2, ...
}

// Assert (logga solo se condizione è falsa)
console.assert(x > 0, 'x deve essere positivo, attuale:', x);

// Stack trace
console.trace('Dove siamo arrivati?');

// Pulisci console
console.clear();

Console Interattiva

// Variabili speciali della console
$0       // Ultimo elemento selezionato in Elements
$1       // Penultimo elemento selezionato
$_       // Risultato dell'ultima espressione
$('div') // Shortcut per document.querySelector
$$('div') // Shortcut per document.querySelectorAll

// Monitorare eventi su un elemento
monitorEvents(document.body, 'click');
monitorEvents(input, ['keydown', 'keyup']);
unmonitorEvents(document.body);

// Copiare negli appunti
copy(JSON.stringify(data, null, 2));
copy($0.outerHTML);

// Ispeziona funzione
debug(myFunction);    // Breakpoint quando chiamata
undebug(myFunction);

// Visualizza listeners
getEventListeners(document.body);

Breakpoints

Tipi di Breakpoint

  • Line breakpoint: Click sul numero riga in Sources
  • Conditional: Si attiva solo se condizione è vera
  • Logpoint: Logga senza fermare l'esecuzione
  • DOM breakpoint: Si attiva su modifiche DOM
  • XHR/Fetch: Si attiva su richieste specifiche
  • Event listener: Si attiva su eventi specifici
  • Exception: Si attiva su errori

Breakpoint Condizionale

// Click destro sul numero riga → "Add conditional breakpoint"
// Inserisci condizione JavaScript:

user.id === 123           // Solo per utente specifico
items.length > 10         // Solo se array grande
error !== null            // Solo se c'è errore
i % 100 === 0             // Ogni 100 iterazioni

// Logpoint (non ferma l'esecuzione)
// Click destro → "Add logpoint"
'Utente:', user.name, 'Items:', items.length

Debugger Statement

function processData(data) {
  // Si ferma qui SOLO se DevTools è aperto
  debugger;

  // Utile per debug condizionale
  if (data.error) {
    debugger;
  }

  return data.map(transform);
}

// Rimuovi prima del deploy!
// O usa: /* eslint-disable-next-line no-debugger */

Navigazione Debug

Controlli Step-by-Step

# Scorciatoie durante il debug

F8 / Cmd+\     → Resume/Pause (continua esecuzione)
F10 / Cmd+'    → Step over (prossima riga, salta funzioni)
F11 / Cmd+;    → Step into (entra nella funzione)
Shift+F11      → Step out (esci dalla funzione)
Ctrl+.         → Step (prossimo statement)

# Comportamento:
Step Over: Esegue la riga, se è una funzione la esegue tutta
Step Into: Se è una funzione, entra nel suo codice
Step Out: Completa la funzione corrente e torna al caller

Call Stack

Il pannello Call Stack mostra la catena di chiamate che ha portato al breakpoint corrente. Clicca su qualsiasi entry per saltare a quel punto del codice e vedere le variabili locali in quel contesto.

Scope

Il pannello Scope mostra tutte le variabili accessibili nel punto corrente:

  • Local: Variabili definite nella funzione corrente
  • Closure: Variabili catturate dalla closure
  • Script: Variabili a livello di modulo
  • Global: Variabili globali (window)

Network Panel

Analisi Richieste

# Filtrare richieste
XHR           → Solo AJAX/Fetch
Fetch         → Solo Fetch API
JS            → Solo JavaScript
CSS           → Solo fogli di stile
Img           → Solo immagini
Media         → Audio/Video
Font          → Web fonts
Doc           → Documenti HTML
WS            → WebSocket
Manifest      → PWA manifest

# Filtri avanzati (nella search box)
larger-than:100K    → File > 100KB
status-code:404     → Solo errori 404
-status-code:200    → Escludi 200 OK
method:POST         → Solo POST
domain:api.example  → Solo dominio specifico
has-response-header:cache-control

Dettagli Richiesta

  • Headers: Request e response headers completi
  • Payload: Body della richiesta (POST, PUT)
  • Preview: Anteprima formattata della risposta
  • Response: Risposta raw
  • Initiator: Cosa ha causato la richiesta
  • Timing: Breakdown dettagliato dei tempi

Source Maps

// webpack.config.js
module.exports = {
  devtool: 'source-map',           // Development
  // devtool: 'hidden-source-map', // Production (no link nel bundle)
};

// vite.config.js
export default {
  build: {
    sourcemap: true
  }
};

// Con source maps, DevTools mostra il codice originale
// (TypeScript, JSX, SCSS) invece del bundle compilato

Performance Panel

Recording

1. Apri Performance panel
2. Click Record (o Ctrl+E)
3. Interagisci con la pagina
4. Click Stop
5. Analizza il flame chart

# Cosa cercare:
- Long tasks (barre rosse > 50ms)
- Layout thrashing (molti recalculate style)
- Scripting time eccessivo
- Blocking JavaScript

Memory Panel

Trovare Memory Leaks

// Pattern comuni di memory leak:

// 1. Event listener non rimossi
element.addEventListener('click', handler);
// Fix: element.removeEventListener('click', handler);

// 2. Closure che trattengono riferimenti
function setup() {
  const hugeData = loadData(); // 10MB
  return () => console.log(hugeData[0]); // Leak!
}

// 3. Timer non puliti
const interval = setInterval(fn, 1000);
// Fix: clearInterval(interval);

// 4. Riferimenti DOM detached
const nodes = [];
function createNode() {
  const div = document.createElement('div');
  nodes.push(div); // Mai rimossi!
}

// Heap Snapshot per investigare
1. Memory panel → Heap snapshot → Take snapshot
2. Interagisci con l'app
3. Take another snapshot
4. Comparison view per trovare oggetti che crescono

Trucchi Utili

Blackbox Script

// Ignora librerie durante lo step-through
// Settings → Blackboxing → Add pattern:

/node_modules/
/jquery\.min\.js/
/react-dom/
/lodash/

// Le funzioni blackboxed vengono "saltate" durante il debug

Snippets

// Sources → Snippets → New snippet
// Salva codice da eseguire velocemente

// Esempio: mostra tutti gli event listener
(() => {
  const elements = document.querySelectorAll('*');
  elements.forEach(el => {
    const listeners = getEventListeners(el);
    if (Object.keys(listeners).length > 0) {
      console.log(el, listeners);
    }
  });
})();

Strumenti Correlati

Per debug e sviluppo:

Conclusione

Il debug efficace richiede:

  • Conoscenza approfondita degli strumenti DevTools
  • Uso strategico dei breakpoint
  • Analisi sistematica dei problemi
  • Comprensione di performance e memory

Investi tempo nell'imparare questi strumenti—ripaga enormemente in produttività.

Per altri strumenti utili, esplora i nostri tool online gratuiti. Per documentazione completa, consulta Chrome DevTools Documentation.