Debug web moderno in Chrome DevTools

Introduzione

Oggi gli autori possono utilizzare molte astrazioni per creare le proprie applicazioni web. Invece di interfacciarsi direttamente con le API di livello inferiore fornite dalla piattaforma web, molti autori sfruttano i framework, gli strumenti di creazione e i compilatori per scrivere le proprie applicazioni da una prospettiva di livello superiore.

Ad esempio, i componenti basati sul framework Angular vengono creati in TypeScript con modelli HTML. All'interno di una struttura, l'interfaccia a riga di comando Angular e il webpack compilano tutto in JavaScript e in un cosiddetto bundle, che viene poi spedito al browser.

Durante il debug o la profilazione delle applicazioni web in DevTools, al momento puoi visualizzare ed eseguire il debug di questa versione compilata del codice anziché del codice che hai effettivamente scritto. Tuttavia, come autore, non è opportuno che:

  • Non vuoi eseguire il debug del codice JavaScript minimizzato, ma del codice JavaScript originale.
  • Quando utilizzi TypeScript, non vuoi eseguire il debug di JavaScript, ma il codice TypeScript originale.
  • Quando utilizzi i modelli come Angular, Lit o JSX, non sempre è consigliabile eseguire il debug del DOM risultante. Ti consigliamo di eseguire il debug dei componenti autonomamente.

In generale, è probabile che tu voglia eseguire il debug del tuo codice così come lo hai scritto.

Anche se le mappe di origine colmano già questa lacuna in una certa misura, c'è molto altro che Chrome DevTools e l'ecosistema possono fare in quest'area.

Diamo un'occhiata.

Confronto tra codice creato e codice implementato

Al momento, quando esplori la struttura di file nel riquadro Origini, puoi vedere i contenuti del pacchetto compilato (e spesso minimizzato). Si tratta dei file effettivi che il browser scarica ed esegue. DevTools lo definisce Codice implementato.

Screenshot della struttura ad albero dei file in Chrome DevTools che mostra il codice implementato.

Questi dati non sono molto pratici e spesso difficili da comprendere. In qualità di autore, vuoi visualizzare ed eseguire il debug del codice che hai scritto, non del Codice implementato.

Per rimediare, ora puoi fare in modo che la struttura ad albero mostri invece il Codice creato. In questo modo l'albero è più simile ai file di origine che puoi vedere nel tuo IDE e questi file sono ora separati dal Codice implementato.

Screenshot della struttura di file in Chrome DevTools che mostra il codice creato.

Per abilitare questa opzione in Chrome DevTools, vai a Impostazioni > Esperimenti e seleziona Raggruppa le origini in alberi creati e implementati.

Screenshot delle impostazioni di DevTools.

"Solo il mio codice"

Quando usi dipendenze o crei su un framework, i file di terze parti possono essere d'intralcio. La maggior parte delle volte vuoi vedere solo il tuo codice, non quello di alcune librerie di terze parti nascoste nella cartella node_modules.

Per rimediare, DevTools ha un'impostazione aggiuntiva attivata per impostazione predefinita: Aggiungi automaticamente script di terze parti noti all'elenco degli elementi da ignorare. Puoi trovarlo in DevTools > Impostazioni > Elenco degli utenti da ignorare.

Screenshot delle impostazioni di DevTools.

Quando questa impostazione è abilitata, DevTools nasconde qualsiasi file o cartella che un framework o uno strumento di creazione ha contrassegnato come da ignorare.

A partire dalla versione Angular v14.1.0, i contenuti delle relative cartelle node_modules e webpack sono stati contrassegnati come tali. Pertanto, queste cartelle, i file al loro interno e altri elementi di terze parti non vengono visualizzati in vari punti in DevTools.

In qualità di autore, non devi fare nulla per attivare questo nuovo comportamento. Spetta al framework implementare questa modifica.

Ignora il codice nelle analisi dello stack

I file elencati di seguito non vengono più visualizzati nelle analisi dello stack. In qualità di autore, ora puoi visualizzare analisi dello stack pertinenti.

Screenshot di un'analisi dello stack in DevTools.

Se vuoi visualizzare tutti i frame di chiamata dell'analisi dello stack, puoi sempre fare clic sul link Mostra altri frame.

Lo stesso vale per gli stack di chiamate visualizzati durante il debug e l'esecuzione del codice. Quando i framework o i bundler informano DevTools degli script di terze parti, DevTools nasconde automaticamente tutti i frame di chiamata irrilevanti e salta qualsiasi codice elencato di ignorare durante il debug del passaggio.

Screenshot del debugger origini DevTools durante il debug.

Il codice inserito nell'elenco di elementi da ignorare nella struttura ad albero dei file

Per nascondere i file e le cartelle inclusi nell'elenco di elementi da ignorare nella struttura ad albero dei file Codice creato nel riquadro Origini, seleziona Nascondi codice elencato da ignorare nella visualizzazione ad albero delle origini in Impostazioni > Esperimenti in DevTools.

Screenshot delle impostazioni di DevTools.

Nel progetto Angular di esempio, le cartelle node_modules e webpack sono ora nascoste.

Screenshot della struttura ad albero dei file in Chrome DevTools che mostra il codice creato con la creazione ma non node_modules.

Ignora il codice elencato nel menu "Apertura rapida"

Il codice nell'elenco di elementi ignorati non è solo nascosto nella struttura ad albero dei file, ma viene anche nascosto dal menu "Apertura rapida" (Ctrl+P (Linux/Windows) o Comando+P (Mac))

Screenshot di DevTools con il menu "Apertura rapida".

Ulteriori miglioramenti alle analisi dello stack

Avendo già esaminato le analisi dello stack pertinenti, Chrome DevTools introduce ancora più miglioramenti alle analisi dello stack.

Analisi dello stack collegate

Quando alcune operazioni sono pianificate per essere eseguite in modo asincrono, le analisi dello stack in DevTools attualmente raccontano solo una parte della storia.

Ad esempio, ecco uno scheduler molto semplice in un file framework.js ipotetico:

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      tasks.push({ f });
    },

    work() {
      while (tasks.length) {
        const { f } = tasks.shift();
        f();
      }
    },
  };
}

const scheduler = makeScheduler();

function loop() {
  scheduler.work();
  requestAnimationFrame(loop);
};

loop();

... e in che modo uno sviluppatore potrebbe utilizzarlo nel proprio codice in un file example.js:

function someTask() {
  console.trace("done!");
}

function businessLogic() {
  scheduler.schedule(someTask);
}

businessLogic();

Quando aggiungi un punto di interruzione all'interno del metodo someTask o quando ispezioni la traccia stampata nella console, non vedi alcun riferimento alla chiamata businessLogic() che è stata la "causa principale" di questa operazione.

Puoi vedere solo la logica di pianificazione del framework che ha portato all'esecuzione dell'attività e nessun breadcrumb nell'analisi dello stack per aiutarti a capire i collegamenti causali tra gli eventi che hanno portato a questa attività.

Un'analisi dello stack di un codice eseguito asincrono senza informazioni su quando è stato pianificato.

Grazie a una nuova funzionalità chiamata "Tagging stack asincrono", è possibile raccontare l'intera storia collegando insieme le due parti del codice asincrono.

L'API Async Stack Tagging introduce un nuovo metodo console denominato console.createTask(). La firma dell'API è la seguente:

interface Console {
  createTask(name: string): Task;
}

interface Task {
  run<T>(f: () => T): T;
}

La chiamata console.createTask() restituisce un'istanza Task che puoi utilizzare in un secondo momento per eseguire i contenuti dell'attività f.

// Task Creation
const task = console.createTask(name);

// Task Execution
task.run(f);

L'attività costituisce il collegamento tra il contesto in cui è stata creata e il contesto della funzione asincrona in esecuzione.

Applicato alla funzione makeScheduler sopra, il codice diventa il seguente:

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      const task = console.createTask(f.name);
      tasks.push({ task, f });
    },

    work() {
      while (tasks.length) {
        const { task, f } = tasks.shift();
        task.run(f); // instead of f();
      }
    },
  };
}

Grazie a ciò, Chrome DevTools ora è in grado di mostrare un'analisi dello stack migliore.

Un&#39;analisi dello stack di un codice eseguito asincrono con informazioni sulla data di pianificazione.

Nota che ora businessLogic() è incluso nell'analisi dello stack. Inoltre, l'attività ha un nome familiare someTask anziché requestAnimationFrame generico come prima.

Inquadrature per le chiamate amichevoli

Durante la creazione di un progetto, i framework spesso generano codice da tutti i tipi di linguaggi di modelli, come i modelli Angular o JSX, che trasformano il codice HTML in un semplice JavaScript che alla fine viene eseguito nel browser. A volte, a questi tipi di funzioni generate vengono dati nomi che non sono molto amichevoli: nomi di una sola lettera dopo essere stati minimizzati o alcuni nomi ambigui o sconosciuti, anche quando non lo sono.

Nel progetto di esempio, un esempio è AppComponent_Template_app_button_handleClick_1_listener, che puoi vedere nell'analisi dello stack.

Screenshot dell&#39;analisi dello stack con il nome di una funzione generato automaticamente.

Per risolvere questo problema, Chrome DevTools ora supporta la ridenominazione di queste funzioni tramite mappe di origine. Se una mappa di origine contiene una voce di nome per l'inizio di un ambito di funzione, il frame di chiamata dovrebbe visualizzare questo nome nell'analisi dello stack.

In qualità di autore, non devi fare nulla per attivare questo nuovo comportamento. Spetta al framework implementare questa modifica.

Prospettive future

Grazie alle aggiunte descritte in questo post, Chrome DevTools può offrirti una migliore esperienza di debug. Ci sono altre aree che il team vorrebbe esplorare. In particolare, verrà spiegato come migliorare l'esperienza di profilazione in DevTools.

Il team di Chrome DevTools invita gli autori dei framework ad adottare queste nuove funzionalità. Il Case study: Better Angular Debugging con DevTools offre indicazioni su come implementare questa funzionalità.