Have you ever wondered about those .js.map or .ts.map files sitting inside of your projects ?
If not, then in next 3 minutes, you’ll get to know about these little angels, because of which you can debug your code in Chrome or Firefox and/or analyse your code coverage.
In this article, we’ll start with a high level overview of source maps, then we’ll have a look at some examples and a live demo of source maps followed by understanding the mapping technique used by source maps.
Definition
Source Maps are the files which create a mapping between your source(original) code and your generated code. In other words, a line in your generated code is representing which line of your source code is determined by source maps.
Example
Let’s understand the above definition through an example of typescript:
Currently, browsers do not support typescript, so when you write some code in a .ts
file and run the tsc
command to compile that file; it basically transpiles the code into javascript that can be executed in a browser.
In the above example, it’s just a simple code and the generated JS can be easily understood by a developer. Problem arises when the TS code is complex then the generated JS is much more complex, which becomes really hard for the developer to understand. And then Source Maps come to the rescue, they map our generated code(JS) to the source code(TS).
Here is an example by thecssninja.
If you want to generate a source map for your TS file, then just put . sourcemap: true
in compilerOptions
of your tsconfig.json file. Changing source map to true will result in generation of one more file as shown in example below
The generated source map file looks something like this :
{“version”: 3,
“file”: “example.js”,
“sourceRoot”: “”,
“sources”: [
“example.ts”
],
“names”: [],
“mappings”: “AAAA;IAAA;IAUA,CAAC;IAPG,8BAAY,GAAZ,UAAa,IAAY;QACrB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,8BAAY,GAAZ;QACI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IACL,cAAC;AAAD,CAAC,AAVD,IAUC”
}
Above you can see that a source map is an object literal containing lots of complex info:
- Version number that the source map is based off
- The file name of the generated code (Your minifed/combined production file)
- sourceRoot allows you to prepend the sources with a folder structure — this is also a space saving technique
- sources contains all the file names that were combined
- names contains all variable/method names that appear throughout your code.
- Lastly the mappings property is where the magic happens using Base64 VLQ (Variable Length Quantity) values. The real space saving is done here.
Analyzing Source Maps
The mappings property is a super big string. Within this string are semicolons (;) that represent a line number within the generated file. A part from mappings string:
Let’s understand what is the meaning of these alien characters.
The above diagram AAgBC
once processed further would return 0, 0, 32, 16, 1 – the 32 being the continuation bit that helps build the following value of 16. B purely decoded in Base64 is 1. So the important values that are used are 0, 0, 16, 1. This then lets us know that line 1 (lines are kept count by the semi colons) column 0 of the generated file maps to file 0 (array of files 0 is example.js), line 16 at column 1.
Hope you got to the overview of Source Maps and the mapping techniques used by them :)