Что такое Source Maps?
В последние несколько недель мы познакомили вас с некоторыми фреймворками JavaScript. Похоже, сейчас самое подходящее время, чтобы представить Source Maps вашему вниманию!
Если вы когда-либо мечтали о том, чтобы существовал простой способ отладки и чтения кода на стороне клиента после его объединения и минимизации, тогда Source Maps помогут сделать вашу жизнь намного проще! По сути, это существует для сопоставления объединенного / минифицированного файла обратно с незавершенным состоянием.
Поскольку Source Maps все еще находятся на ранних этапах, он может воспользоваться вашей помощью! Думаешь, ты мог бы использовать это с пользой? Как вы думаете, это достойно дальнейшего развития?
Начните с исходных карт
Для транскрипции JumpCast и тому подобного, посетите Learnable
JGB: Я здесь с Майклом Мифсудом, веб-разработчиком 99designs, и сегодня Майкл расскажет нам все о Source Maps. Можете ли вы начать с того, чтобы рассказать мне, что такое Source Maps?
Майкл: Карты источников – это просто название способа сопоставления двух эквивалентных файлов. Если у вас есть файл, который был предварительно обработан или иным образом изменен в другой файл, он может отобразить выведенный файл в исходный файл.
JGB: Для чего вы используете Source Maps?
Майкл: Основное использование для этого сейчас – отображение уменьшенного JavaScript в исходный код JavaScript. Таким образом, вы всегда можете добиться максимальной производительности, иметь возможность и контекст ваших исходных файлов, когда вы смотрите на них в отладчике.
JGB: Какие проблемы это решает точно?
Майкл: Хорошо, мы все знаем, что производственный код таинственным образом ломается, когда он никогда не ломается в процессе разработки. Попытка отладить 30 000 символов в длинном однострочном файле JavaScript – это кошмар. Теперь с Source Maps вы можете копаться в нем и видеть, как оно выглядело, когда вы его писали, и у вас было немного контекста.
JGB: Так почему же кто-то хочет иметь возможность отладки?
Майкл: Ты никогда не сможешь контролировать, когда что-то сломается Вы часто можете воспроизвести что-то в производстве, что вы не можете воспроизвести в процессе разработки. Так что это дает вам возможность в тот момент, с полным контекстом, выяснить, что пошло не так.
JGB: Так кто же может использовать Source Maps и какие навыки вам нужны для их использования?
Майкл: По сути это для тех, кто в процессе сборки минимизирует и объединяет файлы. По сути, вы теряете весь контекст. Это становится одним большим беспорядком. Так что любой вид значительного веб-сайта будет делать это как шаг. Концепция живой отладки для всех.
Но делать это в производственной среде невероятно сложно. Если у вас есть Карты источников, вы сможете увидеть, что вы создали сами. Создание исходных карт само по себе немного хлопотно. Это должно быть сделано автоматически, это не то, что вы обычно делаете вручную. Так что если у вас есть команда DevOps или какой-то процесс развертывания, это будет частью этого.
JGB: Так что, если Source Maps настолько полезны, почему они в настоящее время не используются?
Майкл: Как и во всем, это требует времени. Существуют инфраструктурные изменения, которые необходимо внести для автоматизации создания исходных карт, и программное обеспечение, которое их генерирует, мало и далеко друг от друга. Как и все новые вещи HTML5, это живая спецификация. Сейчас он в третьей версии и часто меняется. Поэтому люди не хотят тратить много времени на программное обеспечение, которое может измениться.
Но вы можете использовать сторонние библиотеки. Прямо сейчас он ограничен компилятором Google замыкания, который является библиотекой Java, и Java – это не то, что входит во многие современные веб-стеки или стеки веб-разработки. Поэтому от имени компании требуется время и усилия, чтобы добиться этого. Но есть люди, использующие это. Он будет расти по мере того, как станет более стабильным и простым в использовании.
JGB: Так какое будущее у Source Maps?
Майкл: Ну, сейчас основное применение – это сопоставление минимизированного JavaScript с обычным JavaScript, потому что это отображение один-к-одному. В идеале в будущем вы сможете отобразить любой предварительно обработанный файл из CoffeeScript или SASS в сгенерированный CSS или JavaScript. Сейчас это немного отстает, проблема в том, что больше нет однозначного сопоставления. В SASS есть такие вещи, как смешанные модули, в которых больше нет прямой межстрочной корреляции, и в этом есть логика. Это своего рода следующий шаг или следующая итерация Source Maps.
What Are Source Maps and How to Properly Use Them
You are debugging a web app for a client but the minified version of the Javascript and CSS code makes it impossible to understand what statements the browser is actually executing.
You could break down the original code line by line in your editor putting some “console.log()” statements here and there, or try debugging it from its transformed state.
This is where you could benefit from embracing the use of source maps as a handy tool in your developer toolbox. Much like the name implies, source maps offer a way to map code within a compressed Javascript file back to the original position in a source file, and they offer aid in the department of debugging as well. These are a useful, quick, and straightforward way to figure out how to debug a browser as well as easily read compiled scripts.
So, how exactly do source maps work?
What are Source Maps?
Source Map is a file that maps transformed or transpiled code back to the original source. It allows developers to debug transpiled code in developer tools such as Chrome Developer Tools or Firefox Developer Tools by looking at the original source code including the original line numbers, column numbers, function names, and identifiers that may have been changed during minification or transpiling.
Below is an example of a source map:
It’s just JSON data!
After compiling the code, it will be unreadable to humans as it has been adapted for the computer to take up less space for transfer across the network and improve execution performance.
When the compressed Javascript or CSS files are linked back to their original source the browser will be able to show the precise line of code that the error is occurring within.
This makes debugging much easier.
There are three types of source map you can generate that satisfies different needs.
Inline source map
Inline source maps are simply data URLs that contain the JSON object we saw earlier encoded in base64. It will look something like this:
This is a special comment placed in your normal JavaScript file to tells your browser how to link the compiled code to the original version.
External source map
Source map can be also placed in a separate file. It’s handy for production usage as then loading source maps is optional.
Here is an example of how an external source map is declared directly from the code of the Inspector frontend:
Maybe you don’t want to generate a source map for your production bundle as this makes it effortless to inspect your application. By disabling source maps, you are performing a sort of obfuscation.
Whether or not you want to enable source maps for production, they are handy for staging. Skipping source maps speeds up your build as generating source maps at the best quality can be a complicated operation.
Hidden source map
Hidden source maps give stack trace information only. You can connect them with a monitoring service to get traces as the application crashes allowing you to fix the problematic situations. While this isn’t ideal, it’s better to know about possible problems than not.
How to Use Source Maps
All modern browsers offer complete support for source maps.
If you are using Google Chrome, you can easily see the available source maps by clicking on the “Sources” tab in the Chrome dev tools.
As seen in the image below, you can insert a breakpoint in your original code, and Chrome dev tools will automatically map that breakpoint to the minified line of the source file during execution.
The developer tools for both Chrome and Firefox have built in support for source maps making it even easier to trace the compressed files and debug any errors.
Source Maps & Google Chrome
Chrome is set up very efficiently when it comes to source maps as Google had a large hand in source map specification. It is quite geared toward debugging and that gives it a slight edge on that aspect. Chrome offers a debug extension for inline and external source maps.
Source Maps & Mozilla Firefox
When using the Firefox developer tools for source mapping, the process is somewhat similar without the addition of the extension straight into the browser. You would want to generate the source map and include a comment that would point to the source map.
This would allow the process of being able to see the uncombined script and make debugging much easier, similarly with Chrome.
Source Maps Summary
Source maps are really that handy tool for being able to debug code easily and efficiently while still being able to link back to original source files and see more clearly what the browser is running.
When you combine the use of source maps and the developer tools that Chrome and Firefox have it makes it even easier to debug and view issues directly.
Try Inspector for free and as long as you want
To let everyone interested try a new code execution monitoring tool, Inspector offers a free tier with up to 30,000 monthly transactions included. And it’s not a limited trial. So, you and your team can get familiar with Inspector without the pressure of a deadline.
Создание и использование Source Maps для css и js в GULP 4
Хотелось бы в двух словах рассказать, как настроить Source Maps для GULP 4, но не получится вырвать из контекста просто пару строк кода, поэтому разобью статью на 2 части. Первая будет с базовым кодом для Source Maps, а во второй части будет куча кода из рабочего проекта.
Source Maps нужны для проектов, где происходит сборка нескольких файлов в один, например, компиляция файлов scss в один файл main.min.css или конкатенация js-файлов в один scripts.min.js . Карты источников нужны для того, чтобы быстро вносить правки, и не искать в каком файле задано определенное правило или функция, особенно когда для сборки используются десятки файлов или различных библиотек.
Так будет выглядеть в инспекторе код без Source Maps:
Так будет выглядеть код с использованием Source Maps: 
И по итогу, если нам нужно увеличить отступ снизу у элемента .icon , то нам не нужно искать по всем файлам scss где задано это правило, а с помощью карты источников видим, что данное правило указано в файле _general.scss на 44 строке.
Если вам это не нужно, то дальше можно не читать.
1. Базовый пример вывода Source Maps для js-файла
Где – plugin1() и plugin2() – это какие-то образные плагины, которые занимаются минификацией и конкатенацией js-файлов, например.
Дальше будет много кода из рабочего примера, будет использоваться scss, сборка, минификация, конкатенация и т.д.
2. Кастомизированный пример подключения Source Maps в js-файлах и в css-файлах
Задача для компиляции файла main.min.css с Source Maps
Задача для конкатенации файла scripts.min.js с Source Maps
Все классно, но есть одна проблема.
sourcemaps.write() – не указаны пути для файла *.map, значит карта источников будет записана внутри файла в самый конец, тем самым увеличивая вес файлов более чем в два раза. Это не круто, но зато карты источников будут работать и в Chrome, и в Firefox.
sourcemaps.write(‘.’) – в таком формате source map запишется отдельным файлом в той же папке, что и основной файл, в формате main.min.css.map и scripts.min.js.map.
Проблема с лишним содержимым в виде карты путей решаема.
Source Maps нужны нам только во время разработки, поэтому при билде продашена просто удалим все комментарии из файлов .css и .js – а карта источников записана именно в виде комментария.
Это часть кода из моей таски ‘build’:
По итогу, на продакшене будут чистые минифицированные файлы без лишнего кода и комментариев.
Source Maps: быстро и понятно

Механизм Source Maps используется для отображения исходных текстов программы на сгенерированные на их основе скрипты. Несмотря на то, что тема не нова и по ней уже написан ряд статей (например эта, эта и эта) некоторые аспекты все же нуждаются в прояснении. Представляемая статья представляет собой попытку упорядочить и систематизировать все, что известно по данной теме в краткой и доступной форме.
В статье Source Maps рассматриваются применительно к клиентской разработке в среде популярных браузеров (на примере, DevTools Google Chrome), хотя область их применения не привязана к какому-либо конкретному языку или среде. Главным источникам по Source Maps является, конечно, стандарт, хотя он до сих пор не принят (статус — proposal), но, тем не менее, широко поддерживается браузерами.
Работа над Source Maps была начата в конце нулевых, первая версия была создана для плагина Firebug Closure Inspector. Вторая версия вышла в 2010 и содержала изменения в части сокращения размера map-файла. Третья версия разработана в рамках сотрудничества Google и Mozilla и предложена в 2011 (последняя редакция в 2013).
В настоящее время в среде клиентской разработки сложилась ситуация, когда исходный код почти никогда не интегрируется на веб-страницу непосредственно, но проходит перед этим различные стадии обработки: минификацию, оптимизацию, конкатенацию, более того, сам исходный код может быть написан на языках требующих транспиляции. В таком случае, для целей отладки необходим механизм позволяющий наблюдать в дебаггере именно исходный, человекочитаемый код.
Для работы Source Maps необходимы следующие файлы:
- собственно сгенерированный JavaScript-файл
- набор файлов с исходным кодом использовавшийся для его создания
- map-файл отображающий их друг на друга
Map-файл
Вся работа Source Maps основана на map-файле, который может выглядеть, например, так:
Обычно, имя map-файла складывается из имени скрипта, к которому он относится, с добавлением расширения «.map», bundle.js — bundle.js.map. Это обычный json-файл со следующими полями:
- «version» — версия Source Maps;
- «file» — (опционально) имя сгенерированного файла, к которому относится текущий map-файл;
- «sourceRoot» — (опционально) префикс для путей к файлам-исходникам;
- «sources» — список путей к файлам-исходникам (разрешаются аналогично адресам src тега script, можно использовать file://.);
- «names» — список имен переменных и функций, которые подверглись изменению в сгенерированном файле;
- «mappings» — координаты отображения переменных и функций исходных файлов на сгенерированный файл в формате Base64 VLQ;
- «sourcesContent» — (опционально) в случае self-contained map-файла список строк, каждая из которых содержит исходный текст файла из sources;
Загрузка Source Maps
Для того, чтобы браузер загрузил map-файл может быть использован один из следующих способов:
- JavaScript-файл пришел с HTTP-заголовком: SourceMap: <url> (ранее использовался ныне устаревший X-SourceMap: <url>)
- в сгенерированном JavaScript-файле есть особый комментарий вида:
Таким образом, загрузив map-файл браузер подтянет и исходники из поля «sources» и с помощью данных в поле «mappings» отобразит их на сгенерированный скрипт. Во вкладке Sources DevTools можно будет найти оба варианта.
Для указания пути может использоваться пседопротокол file://. Также, в <url> может быть включено все содержимое map-файла в кодировке Base64. В терминологии Webpack подобные Source Maps названы inline source maps.
Self-contained map-файлы
Код файлов-исходников можно включить непосредственно в map-файл в поле «sourcesContent», при наличии этого поля необходимость в их отдельной загрузке отпадает. В этом случае названия файлов в «sources» не отражают их реального адреса и могут быть совершенно произвольными. Именно поэтому, вы можете видеть во вкладке Sources DevTools такие странные «протоколы»: webpack://, ng:// и т.д
Mappings
Сущность механизма отображения состоит в том, что координаты (строка/столбец) имен переменных и функций в сгенерированном файле отображаются на координаты в соотвествующем файле исходного кода. Для работы механизма отображения необходима следующая информация:
(#1) номер строки в сгенерированном файле;
(#2) номер столбца в сгенерированном файле;
(#3) индекс исходника в «sources»;
(#4) номер строки исходника;
(#5) номер столбца исходника;
Все эти данные находятся в поле «mappings», значение которого — длинная строка с особой структурой и значениями закодированными в Base64 VLQ.
Строка разделена точками с запятой (;) на разделы, соответствующие строкам в сгенерированном файле (#1).
Каждый раздел разделен запятыми (,) на сегменты, каждый из которых может содержать 1,4 или 5 значений:
- номер столбца в сгенерированном файле (#2);
- индекс исходника в «sources» (#3);
- номер строки исходника (#4);
- номер столбца исходника (#5);
- индекс имени переменной/функции из списка «names»;
Каждое значение представляет собой число в формате Base64 VLQ. VLQ (Variable-length quantity) представляет собой принцип кодирования сколь угодно большого числа с помощью произвольного числа двоичных блоков фиксированной длины.
В Source Maps используются шестибитные блоки, которые следуют в порядке от младшей части числа к старшей. Старший 6-й бит каждого блока (continuation bit) зарезервирован, если он установлен, то за текущим следует следующий блок относящийся к этому же числу, если сброшен — последовательность завершена.
Поскольку в Source Maps значение должно иметь знак, для него также зарезервирован младший 1-бит (sign bit), но только в первом блоке последовательности. Как и ожидается, установленный sign бит означает отрицательное число.
Таким образом, если число можно закодировать единственным блоком, оно не может быть по модулю больше 15 (11112), так как в первом шестибитном блоке последовательности два бита зарезервированы: continuation бит всегда будет сброшен, sign бит будет установлен в зависимости от знака числа.
Шестибитные блоки VLQ отображаются на кодировку Base64, где каждой шестибитной последовательности соответствует определенный символ ASCII.

Декодируем число mE. Инверсируем порядок, младшая часть последняя — Em. Декодируем числа из Base64: E — 000100, m — 100110. В первом отбрасываем старший continuation бит и два лидирующих нуля — 100. Во втором отбрасываем старший continuation и младший sign биты (sign бит сброшен — число положительное) — 0011. В итоге получаем 100 00112, что соответствует десятичному 67.
Можно и в обратную сторону, закодируем 41. Его двоичный код 1010012, разбиваем на два блока: старшая часть — 10, младшая часть (всегда 4-битная) — 1001. К старшей части добавляем старший continuation бит (сброшен) и три лидирующих нуля — 000010. К младшей части добавляем старший continuation бит (установлен) и младший sign бит (сброшен — число положительное) — 110010. Кодируем числа в Base64: 000010 — C, 110010 — y. Инверсируем порядок и, в итоге, получаем yC.