Was sind Quellzuordnungen?

Verbessern Sie die Fehlerbehebung im Web mit Quellzuordnungen.

Heute geht es um Source Maps, ein wichtiges Tool in der modernen Webentwicklung, das die Fehlerbehebung erheblich erleichtert. In diesem Artikel werden die Grundlagen von Source Maps erläutert. Außerdem erfahren Sie, wie sie generiert werden und wie sie das Debugging verbessern.

Die Notwendigkeit von Source Maps

Früher haben wir Webanwendungen mit reinem HTML, CSS und JavaScript erstellt und dieselben Dateien im Web bereitgestellt.

Da wir heutzutage jedoch komplexere Webanwendungen erstellen, umfasst Ihr Entwicklungs-Workflow unter Umständen die Verwendung verschiedener Tools. Beispiel:

Ein kurzer Überblick über verschiedene Tools.

Diese Tools erfordern einen Build-Prozess, um Ihren Code in standardmäßigen HTML-, JavaScript- und CSS-Code zu transpilieren, den Browser verstehen können. Zur Leistungsoptimierung ist es außerdem üblich, diese Dateien zu komprimieren (zum Beispiel mit Terser, um JavaScript zu komprimieren und zu mangeln) und zu kombinieren, um ihre Größe zu verringern und für das Web effizienter zu machen.

Mit Build-Tools können wir beispielsweise die folgende TypeScript-Datei transpilieren und in eine einzige JavaScript-Zeile komprimieren. Sie können die Demo in meinem GitHub-Repository ausprobieren.

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

Eine komprimierte Version wäre:

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

Diese Optimierung kann das Debugging jedoch erschweren. Komprimierter Code, der alles in einer einzigen Zeile und kürzere Variablennamen enthält, kann es schwierig machen, die Ursache eines Problems zu finden. Hier kommen Source Maps ins Spiel. Sie ordnen Ihren kompilierten Code dem ursprünglichen Code zu.

Quellzuordnungen generieren

Quellzuordnungen sind Dateien mit Namen, die auf .map enden, z. B. example.min.js.map und styles.css.map. Sie können von den meisten Build-Tools erstellt werden, z. B. Vite, Webpack, Rollup, Parcel oder esbuild.

Einige Tools enthalten standardmäßig Quellzuordnungen, während bei anderen möglicherweise eine zusätzliche Konfiguration erforderlich ist.

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

Die Source Map

Diese Source Map-Dateien enthalten wichtige Informationen darüber, wie der kompilierte Code dem ursprünglichen Code zugeordnet wird, sodass Entwickler mühelos Fehler beheben können. Hier ist ein Beispiel für eine Source Map.

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

Informationen zu den einzelnen Feldern finden Sie in der Source Map-Spezifikation oder im klassischen Artikel zum Aufbau einer Source Map.

Der wichtigste Aspekt einer Source Map ist das Feld mappings. Sie verwendet einen VLQ-Base 64-codierten String, um Zeilen und Orte in der kompilierten Datei der entsprechenden Originaldatei zuzuordnen. Diese Zuordnung kann mit einem Source Map-Visualizer wie source-map-visualization und Source Map Visualization visualisiert werden.

Eine Source Map-Visualisierung.
Die Abbildung zeigt die Visualisierung unseres vorherigen Codebeispiels, das von einem Visualizer generiert wurde.

Die Spalte Generiert auf der linken Seite zeigt den komprimierten Inhalt und die Spalte Original die Originalquelle.

Der Visualizer hat jede Zeile in der Spalte Original und den entsprechenden Code in der Spalte Generated farblich gekennzeichnet.

Der Abschnitt mappings zeigt die decodierten Zuordnungen des Codes. Der Eintrag 65-> 2:2 bedeutet beispielsweise:

  • Generierter Code: Das Wort const beginnt im komprimierten Inhalt an Position 65.
  • Originalcode: Das Wort const beginnt in Zeile 2 und Spalte 2 des Originalinhalts.

Zuordnungseintrag.

Auf diese Weise können Entwickler schnell die Beziehung zwischen dem reduzierten Code und dem ursprünglichen Code erkennen, was die Fehlerbehebung vereinfacht.

Die Entwicklertools des Browsers wenden diese Quellzuordnungen an, damit Sie Fehler bei der Fehlerbehebung schneller und direkt in den Browsern finden können.

Die Entwicklertools wenden eine Source Map an.

Die Abbildung zeigt, wie die Entwicklertools des Browsers Source Maps anwenden und die Zuordnungen zwischen den Dateien.

Quellzuordnungserweiterungen

Quellzuordnungen unterstützen Erweiterungen. Erweiterungen sind benutzerdefinierte Felder, die mit der Namenskonvention x_ beginnen. Ein Beispiel hierfür ist das von den Chrome-Entwicklertools vorgeschlagene Erweiterungsfeld x_google_ignoreList. Unter x_google_ignoreList finden Sie weitere Informationen dazu, wie Sie sich mithilfe dieser Erweiterungen auf Ihren Code konzentrieren können.

Nicht perfekt

In unserem Beispiel wurde die Variable greet während des Build-Prozesses optimiert. Der Wert wurde direkt in die endgültige Stringausgabe eingebettet.

Variaqble Begrüßung ist keine Map.

In diesem Fall können die Entwicklertools beim Debuggen des Codes möglicherweise den tatsächlichen Wert nicht ableiten und anzeigen. Dabei gibt es nicht nur die Entwicklertools von Browsern. Außerdem wird das Monitoring und die Analyse von Code erschwert.

Die Variable „begrüß“ ist nicht definiert.

Dieses Problem ist natürlich lösbar. Eine Möglichkeit besteht darin, die Informationen zum Umfang in die Source Maps aufzunehmen, wie dies bei anderen Programmiersprachen mit ihren Debug-Informationen der Fall ist.

Dies erfordert jedoch, dass das gesamte System zusammenarbeitet, um die Spezifikation und Implementierung der Source Maps zu verbessern. Es gibt eine aktive Diskussion über die Verbesserung der Debug-Fähigkeit mit Source Maps.

Wir freuen uns darauf, Source Maps zu verbessern und das Debugging noch einfacher zu gestalten.