Source Map Explorer

Opens the source map a build leaves beside your bundle, the index tying the shipped file back to the code you actually wrote. It shows which files the bundle is made of, and turns line 1 column 24,500 into somewhere you can go and look.

How to use it

One file feeds two quite different jobs, and it helps to know which one you came for.

  1. Open the map The file next to your bundle ending in .js.map. Open it from disk with the button, or paste it. It is one large block of JSON, so opening is usually easier.
  2. Read the table of files Sorted by how much of the output each one accounts for, with a rollup by folder underneath. That is where you find the package that costs you a hundred kilobytes for one function.
  3. Or look up a position Switch to the second mode, type something like 1:24500, or paste a whole stack trace from a live error. Every line that carries a position is turned back into a place in your source.
Full instructions
One per line. Bare line:column works, and so does a pasted stack trace.

The source map

paste the .js.map, or open it from your disk

What is in it

In depth

Reading a source map without the guesswork

What a source map holds, how to open one and read the file table it produces, how to turn a minified position or a full stack trace back into real file names and lines, and why maps deserve more care than most files get.

Screenshot: The file that knows what your bundle used to be
The file that knows what your bundle used to be as it appears when the page opens.

The file beside the bundle

When a build tool finishes, it leaves two things in the output folder. One is the bundle, the single JavaScript file that runs in the browser. The other is a .js.map file with the same name. That map is a record of where each piece of the bundle came from before it was minified and joined together.

Inside it is a block of JSON. The interesting part is the mappings field, a long string of letters that says, for every point in the output, which original file, line and column it belonged to. There is also a list of file paths and, in most builds, the full text of every original file.

Why you would open one

Two jobs come up over and over. The first is answering the question: which file, or which package, is making this bundle so large? A single dependency can quietly add tens of kilobytes that nobody asked for, and the map is the fastest way to see it. The second job is reading a stack trace from a live error. A production stack trace points at line 1, column 24,500 of a minified file. That is not useful on its own. The map turns it back into the real file name and the real line number, so you can open the right place in your editor without guessing.

  • Finding the dependency that costs the most space in the final output.
  • Turning a crash report from a user into a place you can open in your editor.
  • Checking whether a file you expected to be tree-shaken is still in the bundle.
  • Comparing two builds to see what grew.

Opening a map and reading the file table

Press Open a file and pick the .js.map from your disk. You can also paste the contents, but maps are large blocks of JSON and opening is usually quicker. A map is just text, so dragging it from a file manager works too.

The Show me dropdown starts on What each file contributes. That gives you a table of every source file the bundle contains, sorted by how much of the output each one accounts for. Each row shows the file path, the number of bytes it is responsible for, and its share as a percentage. Below the flat list is a folder rollup that groups everything by directory, so you can see at a glance which installed package is taking the most room.

If the map was built with the original text included, you also get the size of each file before it was minified. When the text is missing, shares are still worked out from the mapping positions, but the before-and-after comparison is not available and the report says so.

Looking up a position in the source

Switch Show me to Where a position really is. A text area appears with the label Positions, or a whole stack trace. Type a position like 1:24500, meaning line 1, column 24,500, and the result tells you which original file that point belongs to, the line and column in that file, and, when the map carries your text, the actual lines of code with the one that matters marked.

You can paste several positions, one per line, and each one is resolved separately. You can also paste an entire stack trace straight from a browser console or an error reporting service. Every line that carries something that looks like a file, line and column is picked out and turned back into its original location. Lines that do not carry a position are left alone, so the trace stays readable.

A walked-through example

Press Try an example to load a small built-in map. The file table appears showing a handful of source files, each with its share. One file accounts for most of the output. The folder rollup below groups them, making the structure clear.

Now switch to the position mode and type 1:200. The result names the original file, shows the line and column in it, and, because this example map carries the text, prints the surrounding lines with the target highlighted. That is the whole loop: a number you could not read becomes a place you can open.

Back in the file table mode, notice the stats at the bottom. They count the total sources, the mapped bytes and any gap at the end of the line that only the bundle could measure. On output minified onto one long line there is a single such gap, so the figures are as good as exact.

Base-64 mappings and why they matter

The mappings string stores each position as a difference from the one before, packed into base-64 characters. That is why a map for a megabyte of code is far smaller than the code itself. It is also why every lookup starts at the beginning of the file. There is no index and no way to skip ahead. The decoder must read every character from the top to reach the one you care about.

This matters in practice for two reasons. First, very large maps take a moment to decode, and the progress bar tells you when it is working. Second, partial maps or maps that have been cut short produce results only up to the point where they stop, with everything after it missing. If a file seems to run out of data halfway through, that is usually a map that was truncated during a failed build or a bad download.

Matching maps to builds

A map is tied to the exact build that made it. If you look up a stack trace from Tuesday against a map built on Wednesday, the line numbers have shifted and the answers will look reasonable but point at the wrong code. There is nothing in the map that warns you about this. It will happily give you a wrong answer that looks right.

The safe habit is to store the map alongside the build artifact. If your deploy pipeline produces a bundle called app.abc123.js, keep app.abc123.js.map beside it. When a crash report arrives, pull the map that matches the version the user was running, not the latest one.

The last line of a bundle usually contains a comment naming its map, something like //# sourceMappingURL=app.js.map. That is how the browser knows where to look. If that line is missing or points at the wrong file, the browser's own dev tools cannot find the map either. Checking that comment is often the first thing to do when stack traces refuse to decode.

What maps reveal about your code

A bundle is minified. Variable names are single letters, comments are gone, and the structure is hard to follow. A map with the original text included reverses all of that. It holds your unminified source, your comments, your file paths, and sometimes even internal notes left in the code for other developers.

That is worth thinking about before publishing maps beside a live site. Anyone who can reach the map can read your code as clearly as you wrote it. For some projects that is fine. For others it is a reason to keep maps off the public server and only load them into an error reporting service that stores them privately.

Most build tools let you choose whether to include the original text. A map without the text is much smaller and still carries enough data for position lookups and the file table shares. What you lose is the ability to see the actual lines of code around a looked-up position.

Your map stays on your own machine

The entire decode runs in your browser. The file is read from your disk, the mappings are unpacked in memory, and the results are drawn on the page. Nothing is sent to a server. There is no upload, no queue, and no account.

That matters here more than it does for most tools, because a source map often contains your complete source code. You can prove it by opening the page, turning off your network connection, and loading a map from disk. Everything still works, because there was never anything on the other end.

Help

The file that knows what your bundle used to be

One file feeds two quite different jobs, and it helps to know which one you came for. The breakdown ranks what the bundle is actually made of, by file and then by folder and package. The lookup takes a single position or a whole stack trace and hands back real file names and line numbers, plus the source lines themselves wherever the map carries them, with the guilty one marked.

Open the map

The file next to your bundle ending in .js.map. Open it from disk with the button, or paste it. It is one large block of JSON, so opening is usually easier.

Read the table of files

Sorted by how much of the output each one accounts for, with a rollup by folder underneath. That is where you find the package that costs you a hundred kilobytes for one function.

Or look up a position

Switch to the second mode, type something like 1:24500, or paste a whole stack trace from a live error. Every line that carries a position is turned back into a place in your source.

Why the numbers are all base sixty-four

The mappings are stored as differences from the point before, packed into base-64 characters. That is why a map for a megabyte of code is so much smaller than the code, and it is also why nothing can read the middle of one without decoding everything before it. There is no index, no seeking, no skipping: every lookup begins at the start of the file. It is worth knowing when you wonder why the tools that read them are slower than they look like they should be.

Good to know

The share is worked out from the map, not the bundle

Each point in the map claims the output up to the next point, which is measurable. The very last point on a line runs to the end of that line, and only the bundle knows where that is. Those bytes are counted and declared rather than guessed. On output minified onto one long line there is a single such gap, so the figures are as good as exact.

The map may carry your whole source

Most builds store the original text inside the map. When it is there you get real sizes and the actual lines around any position you look up. When it is not, you get names and shares and the report says the text is missing.

A map only fits the build it came from

Look up a stack trace from yesterday against today’s map and you will get answers that look perfectly reasonable and point at the wrong lines. Keep the map with the build that made it.

Maps are more revealing than bundles

A map with the text included holds your unminified source, comments and all. That is exactly why this reads it in your browser and sends nothing anywhere — and it is worth thinking about before publishing maps beside a live site.

Common questions

Where do I find the .js.map file?
Beside the bundle it belongs to, usually in the same output folder, with the same name and .map on the end. The last line of the bundle names it.
Can it tell me which package is making my bundle big?
Yes. The folder rollup groups everything under each installed package, so you can see at a glance which dependency is costing the most.
Why are some of the sizes missing?
Because that map was built without the original text in it. Shares of the output are still worked out from the mappings; only the before-and-after file sizes need the text.
Does it need the bundle as well as the map?
No, and it never asks for one. The only thing the bundle would add is the length of the last stretch on each line, which is reported as a known gap instead of being invented.
Is my map uploaded anywhere?
No. It is opened and read on your own device, which matters because a map usually contains your entire source code.