Que sont les cartes sources ?

Les maps de sources sont un outil essentiel du développement Web moderne qui facilite considérablement le débogage. Cette page décrit les principes de base des mappages sources, leur génération et la manière dont elles améliorent l'expérience de débogage.

Besoin de cartes sources

Les premières applications Web étaient peu complexes. Les développeurs déploient des fichiers HTML, CSS et JavaScript directement sur le Web.

Les applications Web plus modernes et complexes peuvent nécessiter différents outils dans leur workflow de développement. Exemple :

Présentation rapide des différents outils.
Quelques outils de développement d'applications Web courants.

Ces outils nécessitent un processus de compilation pour transcompiler votre code en HTML, JavaScript et CSS standards que les navigateurs peuvent comprendre. Il est également courant d'optimiser les performances en minifiant et en combinant ces fichiers à l'aide d'un outil tel que Terser.

Par exemple, à l'aide d'outils de compilation, nous pouvons transcompiler et compresser le fichier TypeScript suivant en une seule ligne de code JavaScript. Vous pouvez l'essayer dans cette démonstration sur 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);
});

Une version compressée serait :

/* 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)}));

Toutefois, la compression de votre code peut rendre le débogage plus difficile. Les mappages de source peuvent résoudre ce problème : en mappant votre code compilé sur le code d'origine, ils peuvent vous aider à trouver rapidement la source d'une erreur.

Générer des cartes sources

Les mappages sources sont des fichiers dont le nom se termine par .map (par exemple, example.min.js.map et styles.css.map). Ils peuvent être générés par la plupart des outils de compilation, y compris Vite, webpack, Rollup, Parcel et esbuild.

Certains outils incluent des cartes sources par défaut. D'autres peuvent nécessiter une configuration supplémentaire pour les générer :

/* 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
  }
})

Comprendre la carte source

Pour faciliter le débogage, ces fichiers de mappage source contiennent des informations essentielles sur la façon dont le code compilé est mappé sur le code d'origine. Voici un exemple de carte de source :

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

Pour comprendre chacun de ces champs, vous pouvez lire la spécification de la carte source ou L'anatomie d'une carte source.

La partie la plus importante d'une carte source est le champ mappings. Il utilise une chaîne VLQ encodée en base64 pour mapper les lignes et les emplacements du fichier compilé avec le fichier d'origine correspondant. Vous pouvez afficher ce mappage à l'aide d'un visualiseur de carte source tel que source-map-visualization ou Source Map Visualization.

Visualisation d'une carte source.
Visualisation de l'exemple de code précédent, générée par un visualiseur.

La colonne généré à gauche affiche le contenu compressé, et la colonne original affiche la source d'origine.

Le visualiseur attribue un code couleur à chaque ligne de la colonne d'origine avec son code correspondant dans la colonne généré.

La section Mappages affiche les mappages décodés du code. Par exemple, l'entrée 65 -> 2:2 signifie:

  • Code généré : le mot const commence à la position 65 dans le contenu compressé.
  • Code d'origine : le mot const commence à la ligne 2 et à la colonne 2 dans le contenu d'origine.
Entrée de mappage.
Visualisation de la mise en correspondance, avec un focus sur l'entrée 65 -> 2:2.

Cela permet aux développeurs d'identifier rapidement la relation entre le code minifié et le code d'origine, ce qui facilite le débogage.

Les outils pour les développeurs de navigateurs appliquent ces cartes sources pour vous aider à identifier rapidement vos problèmes de débogage dans le navigateur.

Outils pour les développeurs appliquant une carte source.
Exemple d'application des outils de développement du navigateur aux mappages de sources et d'affichage des mappages entre les fichiers.

Extensions de la carte source

Les cartes sources acceptent les champs d'extension personnalisés commençant par un préfixe x_. Par exemple, le champ d'extension x_google_ignoreList proposé par Chrome DevTools. Consultez x_google_ignoreList pour en savoir plus sur la façon dont ces extensions vous aident à vous concentrer sur votre code.

Inconvénients des cartes sources

Malheureusement, les mappages de sources ne sont pas toujours aussi complets que vous le souhaitez. Dans notre premier exemple, la variable greet a été supprimée lors du processus de compilation, même si sa valeur est directement intégrée à la sortie de chaîne finale.

La variable "salutation" n'est pas mappée.
La variable greet du code d'origine est manquante dans le mappage.

Dans ce cas, lorsque vous déboguez le code, les outils pour les développeurs risquent de ne pas pouvoir déduire et afficher la valeur réelle. Ce type d'erreur peut rendre la surveillance et l'analyse de votre code plus difficiles.

La variable "salutation" n'est pas définie.
L'outil pour les développeurs ne trouve pas de valeur pour greet.

Il s'agit d'un problème qui doit être résolu dans la conception des cartes sources. Une solution possible consiste à inclure des informations de portée dans les cartes sources de la même manière que les autres langages de programmation le font avec leurs informations de débogage.

Toutefois, pour que cela soit possible, l'ensemble de l'écosystème doit travailler ensemble pour améliorer la spécification et l'implémentation de la carte source. Pour suivre l'amélioration continue de la débogabilité avec les maps sources, consultez la proposition de Source Maps v4 sur GitHub.