Debug web moderno in Chrome DevTools

Introduzione

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

Ad esempio, i componenti basati sul framework Angular vengono creati in TypeScript con modelli HTML. Al suo interno, l'interfaccia a riga di comando Angular e il webpack compilano tutto in JavaScript e in un cosiddetto bundle, che viene quindi inviato 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 tuo codice anziché del codice effettivamente scritto. In qualità di autore, però:

  • Se non vuoi eseguire il debug del codice JavaScript minimizzato, devi eseguire il debug del codice JavaScript originale.
  • Quando utilizzi TypeScript, preferisci non eseguire il debug del codice JavaScript originale.
  • Quando utilizzi i modelli come Angular, Lit o JSX, non sempre vuoi eseguire il debug del DOM risultante. Ti consigliamo di eseguire il debug dei componenti.

In generale, probabilmente vorrai eseguire il debug del tuo codice così come l'hai scritto.

Anche se le mappe di origine colmano già in una certa misura questa lacuna, Chrome DevTools e l'ecosistema possono fare di più in questo ambito.

Diamo un'occhiata.

Confronto tra codice creato e implementato

Al momento, quando esplori la struttura di file nel riquadro Origini, puoi visualizzare i contenuti del bundle compilato e spesso minimizzato. Si tratta dei file effettivi scaricati ed eseguiti dal browser. DevTools definisce questo "Codice di cui è stato eseguito il deployment.

Screenshot della struttura di file in Chrome DevTools che mostra il codice di cui è stato eseguito il deployment.

Non è molto utile e spesso difficile da capire. 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 l'albero mostri il codice creato. Questo rende l'albero più simile ai file sorgente che puoi vedere nel tuo IDE e questi file sono ora separati dal codice distribuito.

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

Per attivare questa opzione in Chrome DevTools, vai a Impostazioni > Esperimenti e seleziona Raggruppa le origini in strutture create e di cui è stato eseguito il deployment.

Screenshot delle impostazioni di DevTools.

"Solo il mio codice"

Quando si utilizzano le dipendenze o si creano sulla base di un framework, i file di terze parti possono ostacolare il processo. La maggior parte delle volte vuoi vedere solo il tuo codice e non quello di alcune raccolte 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 > Ignora elenco.

Screenshot delle impostazioni di DevTools.

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

A partire da Angular v14.1.0, i contenuti delle cartelle node_modules e webpack sono stati contrassegnati come tali. Di conseguenza, queste cartelle, i file al loro interno e altri artefatti di terze parti non vengono visualizzati in varie posizioni in DevTools.

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

Codice incluso nella lista da ignorare nelle analisi dello stack

Questi file in elenco di elementi da ignorare non vengono più visualizzati sono le analisi dello stack. In qualità di autore, ora puoi vedere altre 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 in merito agli script di terze parti, DevTools nasconde automaticamente tutti i frame di chiamata non pertinenti e salta qualsiasi codice incluso nell'elenco degli elementi da ignorare durante il debug dei passaggi.

Screenshot del debugger origini DevTools durante il debug.

Codice nella struttura ad albero dei file da ignorare

Per nascondere i file e le cartelle da ignorare nella struttura ad albero dei file Codice creato dall'autore nel riquadro Origini, seleziona Nascondi il codice incluso nell'elenco degli elementi 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 ora sono nascoste.

Screenshot della struttura di file in Chrome DevTools che mostra il codice creato, ma non mostra node_modules.

Codice da ignorare nel menu "Apertura rapida"

Il codice ignorato non solo è nascosto dalla struttura dei file, ma è anche nascosto dal menu "Apertura rapida" (Ctrl+P (Linux/Windows) o Comando+P (Mac)).

Screenshot di DevTools con il menu "Apertura rapida".

Altri miglioramenti alle analisi dello stack

Avendo già trattato le analisi dello stack pertinenti, Chrome DevTools introduce ulteriori 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 al momento 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.

Al contrario, vedrai solo la logica di pianificazione del framework che ha portato all'esecuzione dell'attività e nessun breadcrumb nell'analisi dello stack per aiutarti a comprendere i collegamenti causali tra gli eventi che portano a questa attività.

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

Grazie a una nuova funzionalità chiamata "Tagging dello stack asincrono", è possibile raccontare l'intera storia unendo 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 seguito 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 quello della funzione asincrona che viene eseguita.

Applicato alla funzione makeScheduler indicata 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 codice eseguito in modo asincrono con informazioni sulla data della pianificazione.

Osserva come businessLogic() è ora incluso nell'analisi dello stack. Non solo, ma l'attività ha un nome familiare someTask anziché requestAnimationFrame generico come prima.

Cornici per una chiamata

Durante la creazione di un progetto, i framework spesso generano codice da tutti i tipi di linguaggi di modello durante la creazione di un progetto, ad esempio i modelli Angular o JSX che trasformano il codice HTML in un semplice codice JavaScript che viene eseguito nel browser. A volte, questi tipi di funzioni generate hanno nomi poco amichevoli, come quelli con una sola lettera dopo averli minimizzati o alcuni nomi poco chiari o sconosciuti anche quando non lo sono.

Nel progetto di esempio, un esempio di questo è 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 generata automaticamente.

Per risolvere questo problema, Chrome DevTools ora supporta la ridenominazione di queste funzioni tramite le mappe di origine. Se una mappa di origine include una voce del nome per l'inizio dell'ambito di una funzione, il frame della chiamata dovrebbe visualizzare quel 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, come migliorare l'esperienza di profilazione in DevTools.

Il team di Chrome DevTools incoraggia gli autori dei framework ad adottare queste nuove funzionalità. Il Case study: Better Angular Debugging with DevTools offre indicazioni su come eseguire questa operazione.