Che cosa sono le mappe di origine?

Migliora l'esperienza di debug web con le mappe di origine.

Oggi parleremo delle mappe di origine, uno strumento fondamentale nello sviluppo web moderno che semplifica notevolmente il debug. In questo articolo, analizzeremo le nozioni di base sulle mappe di origine, come vengono generate e in che modo migliorano l'esperienza di debug.

La necessità di utilizzare le mappe di origine

Ai primi tempi, creavamo applicazioni web con HTML, CSS e JavaScript puri e implementavamo gli stessi file sul web.

Tuttavia, poiché oggi stiamo creando applicazioni web più complesse, il tuo flusso di lavoro di sviluppo potrebbe prevedere l'utilizzo di vari strumenti. Ad esempio:

Una breve panoramica dei vari strumenti.

Questi strumenti richiedono un processo di compilazione per eseguire il transpile del tuo codice in HTML, JavaScript e CSS standard comprensibili per i browser. Inoltre, per ottimizzare le prestazioni, è pratica comune comprimere (ad esempio, utilizzando Terser per minimizzare e manipolare JavaScript) e combinare questi file, riducendone le dimensioni e rendendoli più efficienti per il web.

Ad esempio, con gli strumenti di creazione, possiamo eseguire il transpile e comprimere il seguente file TypeScript in un'unica riga di JavaScript. Puoi giocare con la demo nel mio repository GitHub.

/* A TypeScript demo: example.ts */

document.querySelector('button')?.addEventListener('click', () => {
  const num: number = Math.floor(Math.random() * 101);
  const greet: string = 'Hello';
  (document.querySelector('p') as HTMLParagraphElement).innerText = `${greet}, you are no. ${num}!`;
  console.log(num);
});

Una versione compressa sarebbe:

/* A compressed JavaScript version of the TypeScript demo: example.min.js  */

document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor(101*Math.random());document.querySelector("p").innerText=`Hello, you are no. ${e}!`,console.log(e)}));

Tuttavia, questa ottimizzazione può rendere il debug più complesso. Il codice compresso con tutto in un'unica riga e nomi di variabili più brevi può rendere difficile individuare l'origine di un problema. È qui che entrano in gioco le mappe sorgente, che mappano il codice compilato al codice originale.

Generazione delle mappe di origine in corso...

Le mappe di origine sono file con nomi che terminano con .map (ad esempio, example.min.js.map e styles.css.map). Possono essere generate dalla maggior parte degli strumenti di creazione, ad esempio Vite, webpack, Rollup, Parcel, esbuild e altri ancora.

Alcuni strumenti includono le mappe di origine per impostazione predefinita, mentre altri potrebbero richiedere una configurazione aggiuntiva per riprodurle.

/* Example configuration: vite.config.js */
/* https://vitejs.dev/config/ */

export default defineConfig({
  build: {
    sourcemap: true, // enable production source maps
  },
  css: {
    devSourcemap: true // enable CSS source maps during development
  }
})

Comprendere la mappa di origine

Questi file di mappe di origine contengono informazioni essenziali su come il codice compilato viene mappato al codice originale, consentendo agli sviluppatori di eseguire facilmente il debug. Ecco un esempio di mappa di origine.

{
  "mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
  "sources": ["src/script.ts"],
  "sourcesContent": ["document.querySelector('button')..."],
  "names": ["document","querySelector", ...],
  "version": 3,
  "file": "example.min.js.map"
}

Per comprendere ognuno di questi campi, puoi leggere la specifica delle mappe di origine o questo articolo classico sull'anatomia di una mappa di origine.

L'aspetto più critico di una mappa di origine è il campo mappings. Utilizza una stringa codificata in base 64 VLQ per mappare le linee e le posizioni nel file compilato al file originale corrispondente. Questa mappatura può essere visualizzata utilizzando un visualizzatore delle mappe di origine come source-map-visualizzazione e Visualizzazione mappa di origine.

Una visualizzazione della mappa di origine.
L'immagine mostra la visualizzazione dell'esempio di codice precedente riportato sopra, generato da un visualizzatore.

La colonna generati a sinistra mostra i contenuti compressi, mentre la colonna originale mostra la sorgente originale.

Il colore del visualizzatore codifica ogni riga nella colonna original e il codice corrispondente nella colonna generate.

La sezione mappings (mappature) mostra le mappature decodificate del codice. Ad esempio, la voce 65-> 2:2 significa:

  • Codice generato: la parola const inizia in posizione 65 nei contenuti compressi.
  • Codice originale: la parola const inizia dalla riga 2 e dalla colonna 2 nei contenuti originali.

Mappatura della voce in corso.

In questo modo, gli sviluppatori possono identificare rapidamente la relazione tra il codice minimizzato e il codice originale, rendendo il debug un processo più fluido.

Gli Strumenti per sviluppatori del browser applicano queste mappe di origine per aiutarti a individuare più rapidamente i problemi di debug direttamente nei browser.

Gli Strumenti per sviluppatori applicano una mappa di origine.

L'immagine mostra in che modo gli Strumenti per sviluppatori del browser applicano le mappe di origine e mostra le mappature tra i file.

Estensioni mappa di origine

Le mappe di origine supportano le estensioni. Le estensioni sono campi personalizzati che iniziano con la convenzione di denominazione x_. Un esempio è il campo dell'estensione x_google_ignoreList proposto da Chrome DevTools. Consulta x_google_ignoreList per saperne di più su come queste estensioni ti aiutano a concentrarti sul codice.

Non è perfetto

Nel nostro esempio, la variabile greet è stata ottimizzata durante il processo di creazione. Il valore è stato incorporato direttamente nell'output della stringa finale.

Il saluto Variaqble non è una mappa.

In questo caso, quando esegui il debug del codice, gli strumenti per sviluppatori potrebbero non essere in grado di dedurre e visualizzare il valore effettivo. Questo non è solo un problema per gli strumenti per sviluppatori dei browser. Inoltre, rende più difficili il monitoraggio e l'analisi del codice.

Il greet variabile non è definito.

Questo è ovviamente un problema risolvibile. Uno dei modi è includere le informazioni sull'ambito nelle mappe di origine come fanno altri linguaggi di programmazione con le loro informazioni di debug.

Tuttavia, ciò richiede la collaborazione dell'intero ecosistema per migliorare la specifica e l'implementazione delle mappe di origine. È in corso un discorso attivo su come migliorare la possibilità di debug con le mappe di origine.

Ci auguriamo di migliorare le mappe di origine e di rendere il debug ancora meno complesso.