Что такое map файлы source map
Введение в Javascript Source Maps
Вы когда-нибудь думали, как было бы здорово, если бы слитый в один файл и минифицированный яваскрипт код в production-окружении можено было удобно читать и даже отлаживать без ущерба производительности? Теперь это возможно, если использовать штуку под названием source maps.
Если коротко, то это способ связать минифицированный/объединённый файл с файлами, из которых он получился. Во время сборки для боевого окружения помимо минификации и объединения файлов также генерируется файл-маппер, который содержит информацию об исходных файлах. Когда производится обращение к конкретному месту в минифицированном файле, то производится поиск в маппере, по которому вычисляется строка и символ в исходном файле. Developer Tools (WebKit nightly builds или Google Chrome Canary) умеет парсить этот файл автоматически и прозрачно подменять файлы, как будто ведётся работа с исходными файлами. На момент написания (оригинальной статьи — прим. перев.) Firefox заблокировал развитие поддержки Source Map. Подробнее — на MozillaWiki Source Map.
Пример — правильное определение места в исходном коде
В этом примере можно ткнуть в любом месте textarea правой кнопкой и выбрать пункт «Get original location». При этом будет произведено обращение к файлу-мапперу с передачей строки и номера символа в минифицированном коде, и будет показан соответствующий кусок кода из исходного файла. В консоль будут выведены номер строки и номер символа в исходном файле и другая интересная информация.
Реальное использование
Прежде чем смотреть следующий пример, нужно активировать просмотр source maps в Chrome Canary или WebKit nightly, для этого в свойствах активировать пункт «Enable source maps» (см. скриншот)
Продолжим. Предыдущий пример был интересным, но как это можно использовать? Зайдите на dev.fontdragr.com настроенным браузером Google Chrome и вы увидите, что яваскрипты на странице не скомпилированы и можно смотреть отдельные js-файлы. Это всё благодаря использованию маппера, а на самом деле код на странице скомпилирован. Все ошибки, выводы в лог и точки останова будут маппиться на исходный код, и отлаживать код будет очень удобно. В итоге можно работать с production-сайтом как с тестовым.
Зачем вообще нужны Source Maps?
Google Web Toolkit (GWT) недавно добавил поддержку Source Maps и Ray Cromwell из GWT сделал отличный скринкаст, показывающий работу Source Map в действии.
Другой пример использует библиотеку Google Traceur, которая позволяет писать на ES6 (ECMAScript 6) и компилировать в ES3-совместимый код. Компилятор Traceur также генерирует source map. Посмотрите на пример использования особенностей ES6 (классов и traits), как если бы они поддерживались браузером нативно. Textarea в примере также позволяет писать ES6-код, который будет компилироваться на лету в ES3 и также будет создаваться файл-маппер.
Пример — можно написать код на ES6 и сразу посмотреть в отладчике
Как это работает?
Единственный пока компилятор/минификатор с поддержкой Source Map — Closure compiler (как при компиляции сгенерировать маппер — написано ниже). При минификации JavaScript будет создан и файл-маппер. Пока Closure compiler не добавляет в конец файла специальный комментарий для Google Chrome Canary dev tools о том, что доступен файл-маппер:
Такой комментарий позволяет браузеру искать нужное место в исходном файле, используя файл-маппер. Если идея использовать странные комментарии вам не нравится, то можно добавить к скомпилированному файлу специальный заголовок:
Как и комментарий, это скажет клиенту, где искать маппер для этого файла. Использование заголовка также позволяет работать с языками, которые не поддерживают однострочные комментарии.
Файл-маппер будет скачан только если включено свойство и открыта консоль. Ну и конечно нужно будет залить исходные файлы, чтобы они были доступны по указанным в маппере путям.
Как сгенерировать файл-маппер?
Как уже говорилось выше, нужен будет Closure compiler для минификаци, склейки и генерации файла-маппера для нужных JavaScript-файлов. Для этого нужно выполнить команду:
Внутреннее устройство Source Map
Чтобы лучше понять Source Map, возьмём для примера небольшой файл-маппер и подробно разберём, как устроена «адресация». Ниже приведён немного модифицированный пример из V3 spec:
BASE64 VLQ или как сделать Source Map маленьким
Потенциальные проблемы с XSSI
В спецификации говорится о возможных проблемах с внедрением XSS при использовании Source Map. Избавиться от неё можно, написав в начале своего map-файла » )]> «, чтобы сделать это js-файл невалидным и вызвать ошибку. WebKit dev tools уже умеет её забарывать:
Как видно, первые три символа обрезаются и производится проверка их на соответствие указанному в спецификации невалидному коду и в этом случае вырезается всё до следующего символа перевода строки.
@sourceURL и displayName в действии: eval и анонимные функции
Пример — пропущенный через eval код со сгенерированным именем
Вливайтесь
Есть очень длинное обсуждение по поддержке Source Map в CoffeeScript.
У UglifyJS также есть тикет про поддержку Source Map.
Вы можете помочь, если примете участие в обсуждении и выскажете мнение по поводу нужности поддержки Source Map. Чем больше будет инструментов, поддерживающих эту технологию, тем будет проще работать, так что требуйте её поддержки в вашем любимом OpenSource-проекте.
Source Map не идеален
Есть одна неприятность с использованием Source Map для нормальной отладки. Проблема заключается в том, что при попытке проверить значение аргумента или переменной, определённой в контексте исходного файла, контекст ничего не вернёт, т.к. он на самом деле не существует. Нужен какой-то обратный маппинг, чтобы проверить значение соответствующей переменной/аргумента в минифицированном коде и сопоставить его исходному коду.
Проблема решаемая, а при должном внимании к Source Map могут появиться ещё более интересные его применения.
Инструменты и ресурсы
Source Map — мощный инструмент для разработчика. Он позволяет держать production-код максимально сжатым, но при этом позволяет его отлаживать. Так же полезен для начинающих разработчиков, чтобы посмотреть код, написанный опытными разработчиками, чтобы поучиться правильному структурированию и написанию своего кода без необходимости продираться сквозь минифицированный код. Так чего же вы ждёте? Сгенерируйте Source Map для своего проекта!
Создание и использование Source Maps для css и js в GULP 4
Хотелось бы в двух словах рассказать, как настроить Source Maps для GULP 4, но не получится вырвать из контекста просто пару строк кода, поэтому разобью статью на 2 части. Первая будет с базовым кодом для Source Maps, а во второй части будет куча кода из рабочего проекта.
Так будет выглядеть в инспекторе код без Source Maps:
Так будет выглядеть код с использованием Source Maps:
Если вам это не нужно, то дальше можно не читать.
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.
Проблема с лишним содержимым в виде карты путей решаема.
Это часть кода из моей таски ‘build’:
По итогу, на продакшене будут чистые минифицированные файлы без лишнего кода и комментариев.
Русские Блоги
SourceMap учебник
Редактор рекомендует:FundebugСосредоточьтесь на JavaScript, апплетах WeChat, играх WeChat, Node.js и мониторинге ошибок Java в реальном времени. Это действительно очень хороший сервис по отслеживанию ошибок, которым пользуются многие крупные компании.
1. Введение
SourceMap Информационный файл, в котором хранится соответствие между исходным кодом и скомпилированным кодом.
В интерфейсной работе он в основном используется для решения проблем отладки в следующих трех аспектах:
а) после сжатия кода и запутывания
б. После компиляции в css или JS с использованием других языков, таких как sass и typeScript
В. После объединения нескольких файлов с помощью таких инструментов упаковки, как веб-пакет
В вышеупомянутых трех случаях мы не можем отлаживать так же легко, как исходный код при отладке, для этого требуется SourceMap, чтобы помочь нам преобразовать исходный код в консоли для отладки.
2. Принцип
Фактически, это пара ключ-значение JSON, которая использует кодировку VLQ и специальные правила для хранения информации о местоположении.
Если вас интересует логика, вы можете проверить эту статью, написанную мистером Руаном.«Детали JavaScript Source Map»
3. Как использовать
Эта вещь разработана Google, поэтому в настоящее время может работать только Chrome
Введите настройки режима разработчика
Найдите столбец Sources, установите флажок Allow JS SourceMap и css SourceMap (следует выбрать значение по умолчанию)
Используйте в Gulpgulp-sourcemaps Этот плагин реализован, сначала посмотрим на пример:
После открытия режима разработчика вы увидите окно, аналогичное приведенному выше, в разделе «Источники», чтобы объяснить, что обозначают эти три восклицательных знака:
Модуль рабочего пространства chrome, который предоставляет пространство для размещения локальных файлов в chrome и изменения кода локального файла одновременно с отладкой кода браузером.
4. Подробное объяснение API gulp-sourcemaps
Выше приведено требование к сжатию. Карта должна быть отделена и не должна соблюдаться в исходном файле, иначе сжатие будет больше, чем до сжатия. В настоящее время нам нужно больше понимать использование API.
Официальный файл немного грязный, я разобрался по моим собственным идеям:
Следующее объясняет четыре API по очереди, и использование gulp.src () и gulp.dest () зависит от моей статьи о Gulp.
Поскольку буквально означает API инициализации исходных карт, элементы конфигурации в нем:
исходные карты. API записи (url, <опция>) выходной конфигурации
Дайте больше способов определить исходный путь
Я попробовал это сам, похоже, не имеет никакого эффекта, и это не изменило ни адрес источника, ни выходной адрес. Пожалуйста, обратитесь к описанию следующего официального файла, чтобы попробовать это самостоятельно
The exported mapSources method gives full control over the source paths. It takes a function that is called for every source and receives the default source path as a parameter and the original vinyl file.
SourceMap только для JS и CSS для генерации полного сопоставления, по сравнению с пустым SourceMap по умолчанию, может предотвратить потерю информации.
5. gulp-sourcemaps доступные плагины
gulp-sourcemaps Не все плагины могут быть использованы, как указано выше, вам нужно проверить поддержкуwiki page
В настоящее время поддерживает три основные категории:
Конечно, вы также можете добавить поддержку плагинов напрямую, используйтеvinyl-sourcemaps-apply Я до сих пор не изучал создание плагинов, поэтому сейчас я не буду вдаваться в подробности, у меня будет возможность поговорить об этом позже.
Ну, выше приведен весь контент «SourceMap Tutorial», я надеюсь, что он может помочь вам, если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение
Преимущества использования source map на проектах
При добавлении CSS в проект, обычной практикой является разделение таблицы стилей на несколько модулей или частей. Затем мы импортируем эти части вместе с другими в один индексный файл, используя директиву @import, после чего они будут собраны с помощью LESS препроцессора в один файл CSS. Вот здесь начинается проблема. Браузеры анализируют собранный CSS, а не ваши рабочие файлы, что в конечном итоге делает отладку стилей более сложной. Выяснить, из каких именно файлов получился собранный CSS, практически невозможно.
Проблему с отладкой можно решить, используя source maps. Source maps позволяют ассоциировать собранный код с исходным кодом вашего проекта и значительно облегчить его отладку. Давайте разберёмся, как добавить поддержку source maps в проект с LESS препроцессором.
Не видно, из какого LESS-файла берутся стили, есть только reference на собранный core.css файл. Нужно активировать source maps. Подключим source maps — для этого добавим в Gruntfile.js поддержку Source maps:
При запуске будет создан grunt, начнёт обновляться файл core.css.map, а в core.css в самый конец файла добавится строка:/*# sourceMappingURL=/assets/css/core.css.map*. Теперь в Chrome DevTools мы сможем просматривать исходники LESS вот так (в Firebug не работает, но может есть какие-то дополнения, если поискать):
т.е. видно прямой reference на blocks.less вместо ссылки на скомпилированный core.css.
Можно, конечно, обходиться и без source map, но на большом проекте с множеством LESS-файлов удобство работы с LESS будет ощутимо.
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 необходимы следующие файлы:
Map-файл
Вся работа Source Maps основана на map-файле, который может выглядеть, например, так:
Обычно, имя map-файла складывается из имени скрипта, к которому он относится, с добавлением расширения «.map», bundle.js — bundle.js.map. Это обычный json-файл со следующими полями:
Загрузка Source Maps
Для того, чтобы браузер загрузил map-файл может быть использован один из следующих способов:
Таким образом, загрузив map-файл браузер подтянет и исходники из поля «sources» и с помощью данных в поле «mappings» отобразит их на сгенерированный скрипт. Во вкладке Sources DevTools можно будет найти оба варианта.
Для указания пути может использоваться пседопротокол file://. Также, в может быть включено все содержимое 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 значений:
Каждое значение представляет собой число в формате 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.
Для работы с VLQ весьма полезна одноименная библиотека.