Ulepsz debugowanie stron internetowych dzięki mapom źródeł.
Dziś mówimy o mapach źródłowych – kluczowym narzędziu dla współczesnego tworzenia stron internetowych, które znacznie ułatwia debugowanie. Z tego artykułu dowiesz się, jak działają mapy źródeł, jak są generowane i jak zwiększają one możliwości debugowania.
Potrzeba map źródeł
W dawnych, dobrych czasach tworzyliśmy aplikacje internetowe oparte wyłącznie na HTML, CSS i JavaScript, a następnie wdrażaliśmy te same pliki w sieci.
Ponieważ jednak tworzymy obecnie bardziej złożone aplikacje internetowe, Twój przepływ pracy może wymagać korzystania z różnych narzędzi. Na przykład:
- Języki szablonowe i procesory HTML: Pug, Nunjucks, Markdown.
- Procesory CSS: SCSS, LESS i PostCSS.
- Platformy JavaScript: Angular, React, Vue, Svelte.
- Metaplatformy JavaScript: Next.js, Nuxt, Astro.
- Języki programowania wysokiego poziomu: TypeScript, Dart, CoffeeScript.
- Więcej informacji Lista może być dłuższa.
Narzędzia te wymagają procesu kompilacji w celu transpilacji kodu do standardowego kodu HTML, JavaScript i CSS, który jest zrozumiały dla przeglądarek. W celu optymalizacji wydajności często jest też kompresowana (np. za pomocą skryptu Terser służąca do minifikacji i przekształcania kodu JavaScript) oraz łączenie tych plików, zmniejszając ich rozmiar i zwiększając wydajność w internecie.
Na przykład za pomocą narzędzi do tworzenia możemy przetranspilować i skompresować następujący plik TypeScript do jednego wiersza kodu JavaScript. Możesz zagrać w tę wersję demonstracyjną w moim repozytorium na GitHubie.
/* 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);
});
Wersja skompresowana to:
/* 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)}));
Taka optymalizacja może jednak utrudnić debugowanie. Skompresowany kod zawierający wszystko w jednym wierszu i krótsze nazwy zmiennych mogą utrudniać zlokalizowanie źródła problemu. Właśnie tu do akcji wkraczają mapy źródłowe – mapują skompilowany kod z powrotem na oryginalny kod.
Generuję mapy źródeł
Mapy źródłowe to pliki o nazwach kończących się znakami .map
(np. example.min.js.map
i styles.css.map
). Można je generować za pomocą większości narzędzi do kompilacji, takich jak Vite, pakiet internetowy, Rollup, Parcel czy esbuild.
Niektóre narzędzia zawierają domyślnie mapy źródeł, a inne mogą wymagać dodatkowej konfiguracji do ich wygenerowania.
/* 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
}
})
Informacje o mapie źródeł
Pliki map źródłowych zawierają kluczowe informacje o tym, jak skompilowany kod jest mapowany na oryginalny kod, co ułatwia programistom debugowanie. Oto przykład mapy źródeł.
{
"mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
"sources": ["src/script.ts"],
"sourcesContent": ["document.querySelector('button')..."],
"names": ["document","querySelector", ...],
"version": 3,
"file": "example.min.js.map"
}
Aby zapoznać się z każdym z tych pól, możesz przeczytać specyfikację mapy źródłowej lub ten klasyczny artykuł na temat budowy mapy źródeł.
Najważniejszym aspektem mapy źródłowej jest pole mappings
. Używa ciągu zakodowanego w standardzie VLQ zakodowanym w standardzie 64 do mapowania wierszy i lokalizacji ze skompilowanego pliku na odpowiedni oryginalny plik. Mapowanie to można zwizualizować za pomocą wizualizacji mapy źródłowej, takiej jak source-map-Visualization czy Wizualizacja mapy źródeł.
Kolumna wygenerowane po lewej stronie pokazuje skompresowaną treść, a kolumna oryginalna – oryginalne źródło.
Wizualizacja koduje poszczególne wiersze w kolumnie original (oryginał) i odpowiadający im kod w kolumnie generated (wygenerowane).
Sekcja mappings przedstawia zdekodowane mapowania kodu. Na przykład wpis 65-> 2:2
oznacza:
- Wygenerowany kod: słowo
const
zaczyna się na pozycji 65 w skompresowanej treści. - Kod oryginalny: słowo
const
zaczyna się w wierszu 2 i kolumnie 2 w oryginalnej treści.
Dzięki temu deweloperzy mogą szybko zidentyfikować relację między zminimalizowanym a oryginalnym kodem, co usprawnia debugowanie.
Narzędzia dla programistów w przeglądarce stosują te mapy źródeł, aby pomóc Ci szybciej wyłapać problemy z debugowaniem bezpośrednio w przeglądarce.
Obraz pokazujący, jak Narzędzia dla programistów w przeglądarce stosują mapy źródeł i pokazują mapowania między plikami.
Rozszerzenia mapy źródeł
Rozszerzenia pomocy map źródeł. Rozszerzenia to pola niestandardowe, których nazwa zaczyna się od konwencji nazewnictwa x_
. Jednym z przykładów jest pole rozszerzenia x_google_ignoreList
proponowane przez Narzędzia deweloperskie w Chrome. Więcej informacji o tym, jak te rozszerzenia pomogą Ci skupić się na kodzie, znajdziesz w zapisie x_google_ignoreList.
Nie jest doskonała
W naszym przykładzie zmienna greet
została zoptymalizowana podczas procesu kompilacji. Wartość została umieszczona bezpośrednio w wyniku końcowego ciągu znaków.
W takim przypadku podczas debugowania kodu narzędzia dla programistów mogą nie być w stanie wywnioskować i wyświetlić rzeczywistej wartości. To nie jest tylko wyzwanie dla narzędzi dla programistów w przeglądarce. Utrudnia to też monitorowanie i analizę kodu.
Ten problem można oczywiście rozwiązać. Jednym ze sposobów jest uwzględnienie informacji o zakresie w mapach źródłowych, tak jak w przypadku innych języków programowania.
Wymaga to jednak współpracy całego ekosystemu w celu ulepszenia specyfikacji map źródłowych i ich implementacji. Toczy się aktywna dyskusja na temat zwiększania możliwości debugowania za pomocą map źródeł.
Zamierzamy ulepszyć mapy źródeł i sprawić, że debugowanie będzie jeszcze łatwiejsze.