SourceMap¶
Why Do We Need SourceMap?¶
In the past, we built web applications using only HTML, CSS, and JavaScript, deploying the same files to the web.
Now, as we build more complex web applications, your development workflow may involve using various tools. For example:
-
Template languages and HTML preprocessors: Pug, Nunjucks, Markdown
-
JavaScript frameworks: Angular, React, Vue, Svelte
-
Advanced programming languages: TypeScript, Dart, CoffeeScript
-
...
These tools require a build process to transpile your code into standard HTML, JavaScript, and CSS that browsers can understand. Additionally, to optimize performance, it is common practice to minify (for example, using Terser to reduce and mangle JavaScript) and concatenate these files, thereby reducing their size and improving web page efficiency.
For instance, using a build tool, we can transpile and minify the following TypeScript file into one line of JavaScript.
/* 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
console.log(num);
});
The minified version looks like this:
/* A compressed JavaScript version of the TypeScript demo: example.min.js */
document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor
However, this optimization increases the difficulty of debugging. If the minified code places everything on one line and uses short variable names, it becomes challenging to pinpoint the root cause of issues. This is where source maps come into play—source maps map your compiled code back to the original code.
How to Generate SourceMap?¶
Source maps are files with the .map extension (e.g., example.min.js.map and styles.css.map). Most build tools can generate source maps, such as Vite, webpack, Rollup, Parcel, esbuild, etc. Some tools include source maps by default, while others may require additional configuration to generate them.
/* 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
}
})
Understanding SourceMap¶
These source map files contain important information about how the compiled code maps back to the original code, making it easier for developers to debug. Below is an example of a 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"
}
The most critical part of a source map is the mappings
field. It uses a VLQ base 64 encoded string to map lines and positions in the compiled file to corresponding original files. You can use tools like source-map-visualization and source map visualization to visually present this mapping and verify file availability.
For example, a visual chart generated by the source-map-visualization tool for the example code.
The left generated column shows the minified content, while the original column displays the original source.
The visualization tool color-codes each line in the original column and the corresponding code in the generated column. The mappings section shows the decoded code mappings. For example, entry 65-> 2:2 indicates:
- Generated code: The word
const
starts at position 65 in the minified content. - Original code: The word
const
starts from line 2 and column 2 in the original content.
This way, developers can quickly determine the relationship between the minified code and the original code, making the debugging process smoother.
Browser developer tools apply these source maps to help you identify and debug issues faster directly within the browser.