В современной разработке ваш код сильно отличается от кода на «боевом» сервере (production) после компиляции, минификации, объединения и разных оптимизаций. Тут-то и вступают в игру карты кода (source maps), показывая точное соответствие элементов готового рабочего кода проекта и вашего кода разработки. В этом вводном уроке мы возьмём простой проект и запустим его с помощью различных компиляторов JavaScript с целью посмотреть работу карт кода в браузере.
Кодовые карты дают независимый от языка способ показа соответствия рабочего кода и исходных кодов (sources), написанных вами при разработке. Когда вы после сборки проекта посмотрите на весь подготовленный массив кодов, станет очень сложно найти соответствие участка конечного кода и его исходных строчек. Карта кода хранит эти соответствия, поэтому, когда мы запросим, например, место ошибки, то она покажет точное место её в исходном файле! Это даёт огромную пользу разработчикам, потому что код становится читаемым и даже отлаживаемым!
В этом уроке будем компилировать очень простой кусочек кодов JS + SASS, а затем просмотрим исходные файлы в браузере с помощью кодовых карт. Скачиваем демо-файлы — и приступаем!
Обратите внимание, что к моменту написания статьи Chrome версии 23 поддерживает JS и SASS SourceMaps. Firefox тоже получит поддержку в ближайшем будущем, так как эта тема у него в активной стадии развития. С этими оговорками, давайте посмотрим, как пользоваться картами кодов в браузере.
Прежде всего, нам нужно включить поддержку меппинга в настройках:
1) открыть окно Chrome Developer Tools: View -> Developer -> Developer Tools (F12);
2) нажать «Settings» в правом нижнем углу;
3) выбрать «General» и “Enable source maps”.
![](https://habrastorage.org/r/w1560/files/d43/001/89e/d4300189ec974a70a9cb8c76d26306d2.png)
Скачайте демо-архив (ссылка на примеры переводчика, проверенные на момент перевода) и откройте каталог «start». Файлы и структура каталога довольно просты — немного несложного JavaScript в scripts/script.js. После открывания index.html скрипт меняет цвет фона страницы по вводу кода цвета пользователем.
![](https://habrastorage.org/r/w1560/files/022/02b/8a2/02202b8a287b4f6490be1202615028b4.png)
Посмотрите на простые скрипты в файлах на JavaScript, TypeScript и CoffeeScript.
Используя различные компиляторы, мы создадим сборку и сгенерируем соответствующие файлы кодовых карт.
Мы будем использовать 5 различных способов генерации скомпилированного и минимизированного скрипта вместе с ассоциированной картой. Вы можете перебрать все варианты или использовать только знакомый вам компилятор.
Варианты:
1. Closure Compiler.
2. GruntJS с JSMin.
3. Uglifyjs 2.
4. CoffeeScript Redux.
5. TypeScript.
Гугловский Closure Compiler — это инструмент оптимизации JavaScript. Он анализирует код, удаляет ненужные кусочки, а оставшееся — минифицирует. Кроме того, может генерировать Source Map.
Делаем следующие шаги для создания оптимизированной версии скрипта:
![](https://habrastorage.org/r/w1560/files/6e5/f1b/aea/6e5f1baeae7b421e88c605e874179670.png)
Когда мы открываем
Обратите внимание, что Closure Compiler использует 2 варианта —
Теперь просмотр скриптов в браузере через панель разработчика покажет оба файла — оригинал и оптимизированный
Попробуйте отладку с точками останова. Наблюдаемые выражения и переменные пока недоступны при просмотре исходников. Будем надеяться, что в будущем они появятся!
![](https://habrastorage.org/r/w1560/files/d44/bbd/5d1/d44bbd5d1e3a4e21ada5371846a96e2d.png)
Если вы уже используете Grunt.js для сборки проектов, то он сейчас пригодится для кодовых карт из программы JSMin. Код будет не только минифицирован, но также будет создана карта кодов. (Надо вспомнить, что работа
Шаги показывают, как создать оптимизированную версию с плагином
1. Установите
2. (Для версии 0.3.х). Установите плагин grunt-jsmin-sourcemap. При этом будет создан каталог
3. Отредактируйте созданный
4. Вернитесь к командной строке и запустите grunt:
Это выполнит задачу jsmin-sourcemap как задачу по умолчанию, сформулированную в файле
5. Убедитесь, что в созданном файле Source Map script.jsmin-grunt.js.map прописан файл исходников:
(На самом деле там прописался
6. Раскомментируйте
С
![](https://habrastorage.org/r/w1560/files/f21/9d5/1db/f219d51db764412f815ef1878b81e58e.png)
UglifyJS2 — другой оптимизатор-компрессор JS. Как и в 2 прежних случаях, создаются оптимизированный файл скрипта, добавляется URL кодовой карты и сам файл карты, содержащий соответствия между сжатыми и исходными операторами JavaScript. Для использования выполните в каталоге "
1. Инсталлируйте модуль uglify-js (создасстся каталог
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/9ec/85e/dd4/9ec85edd4af6df2dca01191b0d8490b1.png)
2. В каталоге “
3. В
![](https://habrastorage.org/r/w1560/files/88a/36d/7f8/88a36d7f808c404c8460d29f470c3243.png)
В первых 3 вариантах требовался только 1 шаг оптимизации. Для языков типа CoffeeScript нужно 2 шага: из CoffeeScript в JavaScript, а затем — в оптимизированный JS. Рассмотрим, как создать многоуровневую кодовую карту — из CoffeeScript и из компилятора CoffeeScript Redux (потому что исходный Coffeescript не поддерживал карт до версии 1.6.1 — прим. перев.).
Перейдите в каталог "
1. Установим CoffeeScript с опцией -g возможности глобального вызова.
2. Компилируем
3. Установим CoffeeScript Redux:
4. Создадим файл маппинга
5. Убедитесь, что в самом конце файла
6. Убедитесь, что файл
1. Наконец, используем UglifyJS, чтобы сжать JS и создать кодовую карту. На этот раз сборщик примет кодовую карту от CoffeeScript, чтобы мы могли добраться до исходных кодов. Выполните команду в "
2. Убедитесь, что файл карты кодов имеет правильную ссылку вида
… и правильные ссылки на исходные коды вида
![](https://habrastorage.org/r/w1560/files/11a/274/8a1/11a2748a1edc4d54b3cb41616c6fae1f.png)
TypeScript, как и CoffeeScript, тоже требует 2 этапа: TypeScript -> простой JavaScript -> минифицированный JavaScript. Поскольку скрипт использует плагин jQuery, нужно будет 2 файла TypeScript с именами
Перейдите в каталог «scripts» в режиме командной строки и выполните:
Команда создаст файл
Как и для CoffeweScript, следующий шаг использует UglifyJS:
Убедитесь, что ссылки в
![](https://habrastorage.org/r/w1560/files/21d/754/199/21d7541990274f4da738d23d725aeceb.png)
Кроме JavaScript, Chrome в настоящее время поддерживает SASS и SCSS для карт кодов. Для меппинга SASS давайте изменим некоторые настройки в Хроме и затем скомпилируем SASS в CSS с отладочными параметрами.
1. Перед изменением каких-либо настроек обратите внимание, что при наблюдении элемента из окна инструментов разработчика будем видеть только ссылку на CSS. Это не то, что нужно.
![](https://habrastorage.org/r/w1560/files/358/e11/2c8/358e112c804d4b5db780acbb7bc7c30c.png)
2. Заходим в chrome://flags/.
3. Устанавливаем «Enable Developer Tools experiments» (в русской версии Хрома — «Включить экспериментальные инструменты разработчика»).
![](https://habrastorage.org/r/w1560/files/188/ede/2b7/188ede2b757d4ac58a51c9fb85fb9419.png)
В Windows:
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/0eb/966/77c/0eb96677cd32ba523a4df863a2b074cf.png)
4. Открываем
![](https://habrastorage.org/r/w1560/files/2b9/efc/d29/2b9efcd295b448d5a453d9127cd3350b.png)
В Windows:
Настройки (☰) -> Инструменты -> Инструменты разработчика -> Settings (⏣ в правом нижнем углу) -> Experiments -> Support for Sass.
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/189/80b/df7/18980bdf774bcf2fab13caa267b34e83.png)
5. Компилируем SASS с такими параметрами отладки в каталоге "
6. Убедитесь, что окно Developer Tools переоткрыто и страница перезагружена.
7. Теперь, когда проверяем элемент в Dev.Tools, будем видеть доступ к SASS-файлу.
![](https://habrastorage.org/r/w1560/files/bf8/c92/2a3/bf8c922a33734c028c30c70e0e71c3b9.png)
Кроме простого просмотра SASS, если запущен LiveReload в фоне, то при изменении SASS-файла страница тоже будет изменяться.
Теперь — откроем проект в Firefox и посмотрим через Firebug. В нём тоже будет доступен просмотр SASS-файла.
![](https://habrastorage.org/r/w1560/files/b2a/d07/871/b2ad078715f44abb9b41a2b52c10af5d.png)
Если мы посмотрим любой
1. version: версия карты (обычно 3).
2. file: имя выходного файла.
3. sources: имя исходного файла.
4. names: символы, используемые для соответствий.
5. mappings: данные соответствий.
![](https://habrastorage.org/r/w1560/files/02c/fc0/9e6/02cfc09e6f594ae69e51d3df65b39bfc.png)
Карты кодов всё ещё находятся в стадии активной разработки, но уже есть некоторые заметные ресурсы в Сети. Обязательно посмотрите такие ссылки, чтобы узнать больше.
Надеюсь, что практика использования нескольких компиляторов показала потенциал карт кодов. Хотя функциональность сейчас ограничена, в будущем есть основания ожидать возможности полноценной отладки, в том числе, в виде доступа к переменным и выражениям.
(от перев.) О технологии работы с компилированным кодом в браузере (SourceMap) уже была подробная статья (перевод) примерно год назад. Сейчас эта технология настойчиво отвоёвывает своё место под солнцем. Например, тогда разговоры о маппинге компиляций только велись, а сейчас с версии 1.6.1 поддержку создания map-файлов получил компилятор Coffeescript. В Jetbrains Webstorm 6.0/Phpstorm (март 2013) появилась поддержка SourceMap для работы с кодом. Typescript имеет поддержку с версии 0.8.1 (ноябрь 2012). Все понимают что время ручной работы с «ассемблером» на фронтенде проходит, всем надо знать, откуда у кода ноги растут. Речь даже не идёт о начальном применении расшивки кодов минифицированных файлов — в UglifyJS, Closure Compiler и GWT (как минимум) они поддерживаются. Речь — именно о компиляторах кода JS и CSS.
Вот и недавно (в январе 2013) появилась эта большая обучающая статья, поясняющая на примерах, как работает технология кодовых карт. Хотя первая статья тоже была подробной, но не помешает и вторую иметь в переводе, она описывает то же самое другими словами и иллюстрациями, и переходит к практике — к примерам.
Перейти порог от обычного знания к опыту всегда составляет некоторый барьер. Используя учебные файлы, чтобы увидеть результаты создания файлов кодовых карт, мы между делом получим у себя на компьютере рабочую среду для сборки собственных проектов — все компиляторы и минификаторы, о которых знали, но боялись использовать, у нас будут в сборе, и останется только писать свой код на одном из экзотических до последнего времени сахарных языков фронтенда.
Обратите внимание, что если будете использовать новую версию сборщика Grunt 0.4+, то для неё будут нужны несколько другие настройки, чем описаны в статье. Подробнее о переходе с 0.3.9 на 0.4х — в habrahabr.ru/post/170937.
Автор использовала скриншоты из Мас. Для Хрома они сильно отличаются в области настроек браузера от Windows-версии, поэтому в некоторых местах добавлены скриншоты из русской версии Хрома в Windows.
Для кроссбраузерной разработки предпочтительно иметь возможность работы в любой из основных систем. Если с Linux и MacOS вопросов не возникает, то важно проверить, насколько успешно все примеры работают под Windows. В процессе перевода примеры проверялись и дорабатывались в среде Windows XP и на современных (на апрель 2013) версиях программ. В результате, в 2 из 5 примеров сделаны доработки, выложенные в статье-переводе как замечания и дополнения. (Автору статьи отправлено сообщение о доработках.) Они помогут приблизить примеры к реальности — как в плане поддержки новых версий (особенно Grunt 0.4 и Coffeescript 1.6.1), так и уверенности в работоспособности всех функций на Windows.
Следующая особенность — архив на гитхабе автора. Из-за того, что в нём есть пути длиной больше 260 символов, он полностью не раскрывается в WinRar (но это не мешает использовать стартовые файлы для примеров, у которых короткие пути и выполнить с ними все примеры). Чтобы просмотреть и распаковать (из любопытства) весь архив, в котором лежат инсталлированные после выполнения всех примеров файлы, нужно использовать 7zip или другой архиватор, отличный от WinRar.
Комментариев, замечаний и переделок накопилось достаточно много (Здесь и далее они будут выделяться форматом «цитирования» для удобства различения.) Тем не менее, это не новая статья, а перевод, с замечаниями и учётом местных и кириллических особенностей. Потому что надо отдать дань хорошей и редкой организации большой работы по отношению к популяризации новой технологии.
Но, так как обе статьи по этой теме — переведённая год назад и рассматриваемая — устарели (много не соответствующих нынешнему моменту утверждений), в этом, так сказать, переводе затронуты все вопросы, чтобы статья стала современным практическим руководством как по меппингу, как и по состоянию инструментов и браузеров на сегодня.
Что такое карты кода (source maps)?
Кодовые карты дают независимый от языка способ показа соответствия рабочего кода и исходных кодов (sources), написанных вами при разработке. Когда вы после сборки проекта посмотрите на весь подготовленный массив кодов, станет очень сложно найти соответствие участка конечного кода и его исходных строчек. Карта кода хранит эти соответствия, поэтому, когда мы запросим, например, место ошибки, то она покажет точное место её в исходном файле! Это даёт огромную пользу разработчикам, потому что код становится читаемым и даже отлаживаемым!
В этом уроке будем компилировать очень простой кусочек кодов JS + SASS, а затем просмотрим исходные файлы в браузере с помощью кодовых карт. Скачиваем демо-файлы — и приступаем!
Поскольку в примерах будет работать современная версия Grunt (0.4), рекомендуется скачивать не примеры автора, а обновлённые примеры переводчика. В них лежат как стартовые файлы, так и результаты инсталляций и работы примеров, чтобы можно было проверить правильность и успешность своих действий --прим.перев. .
Браузеры
Обратите внимание, что к моменту написания статьи Chrome версии 23 поддерживает JS и SASS SourceMaps. Firefox тоже получит поддержку в ближайшем будущем, так как эта тема у него в активной стадии развития. С этими оговорками, давайте посмотрим, как пользоваться картами кодов в браузере.
(прим. перев.:) В этой статье в конце имеется пример поддержки SourceMap для SASS в Firefox+Firebug. Кроме того, новое о Firefox: Future of Firefox DevTools (17 Mar 2013) или в переводе:
«Поддержка CoffeeScript. Для её реализации мы сделали поддержку SourceMap. Nick Fitzgerald продемонстрировал версию отладчика, поддерживающего SourceMap и CoffeeScript
Работа Ника помогает поддерживать в том числе минификацию файлов CSS и JS.»
*) wiki.mozilla.org/DevTools/Features/SourceMap
Source Maps в Хроме
Прежде всего, нам нужно включить поддержку меппинга в настройках:
1) открыть окно Chrome Developer Tools: View -> Developer -> Developer Tools (F12);
2) нажать «Settings» в правом нижнем углу;
3) выбрать «General» и “Enable source maps”.
![](https://habrastorage.org/files/d43/001/89e/d4300189ec974a70a9cb8c76d26306d2.png)
Для Windows (от перев.):
1) настройка и управление (в правом верхнем углу) (F12);
2) в окне разработчика — «Settings» в правом нижнем углу;
3) выбрать «General» и “Enable source maps” в блоке «Sources».
Установка
Скачайте демо-архив (ссылка на примеры переводчика, проверенные на момент перевода) и откройте каталог «start». Файлы и структура каталога довольно просты — немного несложного JavaScript в scripts/script.js. После открывания index.html скрипт меняет цвет фона страницы по вводу кода цвета пользователем.
![](https://habrastorage.org/files/022/02b/8a2/02202b8a287b4f6490be1202615028b4.png)
/start
├── index.html
├── /scripts
│ ├── jquery.d.ts
│ ├── script.coffee.coffee
│ ├── script.js
│ └── script.typescript.ts
└── /styles
├── style.css
└── style.sass
Посмотрите на простые скрипты в файлах на JavaScript, TypeScript и CoffeeScript.
Используя различные компиляторы, мы создадим сборку и сгенерируем соответствующие файлы кодовых карт.
Мы будем использовать 5 различных способов генерации скомпилированного и минимизированного скрипта вместе с ассоциированной картой. Вы можете перебрать все варианты или использовать только знакомый вам компилятор.
Варианты:
1. Closure Compiler.
2. GruntJS с JSMin.
3. Uglifyjs 2.
4. CoffeeScript Redux.
5. TypeScript.
После тестирования и доработки примеров до актуальных версий программ парк примеров пополнился двумя вариантами.
2.а GruntJS (0.4.х) с JSMin.
4.а CoffeeScript — не Redux, а оригинальный, версии 1.6.2.
В первом — подробно описана установка новой версии, сильно отличающаяся от актуальной до февраля 2013 версии 0.3.х. Во втором — запуск и тестирования маппинга, появившегося с версии 1.6.1 в Coffeescript в феврале 2013. (с сентября 2012 эту роль исполнял клон — Coffeescript Redux.)
(от перев.) Первое же знакомство с кодом и предлагаемым способом переключения вариантов вызывает смущение. Нет, автором проделана большая работа и приведены потрясающие технологии. Статья отлично оформлена. Но интерфейс пользования неожиданно хромает. Способ переключения вариантов через запись и стирание комментариев противоречит идеологии подхода автоматизированной сборки — всё должно быть максимально управляемым. Показ вариантов — тоже. Ничто не мешает переключать варианты через URL страницы. Напишем переключатель, который в зависимости от параметра option в якоре загрузит тот или иной скрипт во время загрузки страницы. Это не динамическая одностраничная загрузка, хотя недалеко до неё, но уже лучше, чем переключение в коде.
var lHash = location.hash.substr(1).split('='); if(lHash && lHash.length ==2 && lHash[0] =='option') var optionName = lHash[1]; if(optionName && !parseInt(optionName)) optionName = {closure:1,jsmin:2,uglifyjs:3,coffeescript:4,typescript:5}[optionName.toLowerCase()]; console.log(optionName); optionName = optionName ||0; var loadScript; (loadScript = function(i){ var scr = document.createElement('SCRIPT'); scr.setAttribute('type', 'application/javascript'); scr.src ='scripts/script.' + ('|closure|jsmin-grunt|uglify|coffee.min|typescript.min'.split('|')[i]) +(i?'.':'') +'js'; document.getElementsByTagName('head')[0].appendChild(scr); })(optionName);
Теперь мы избавились от кучи комментариев в коде, необходимости следить за ними и переключать. Добавление якоря #option=<число> или #option=<имя_примера> или остутствие (или ошибка формата) якоря вызовут к исполнению нужный скрипт из вариантов, перечисленных в scr.src. В дальнейшем можно добавлять свои варианты под своими именами.
И переключатель бекграунда какой-то недружественный — требует шарпа перед кодом. Понятно желание использовать цвета в словесной форме, но мало кто привык с ними работать. Подправим:
var colr = $("#color").val().toUpperCase() , cL = colr.length; for(var i in cL) if(cL[i] <'0'|| cL[i] >'9'&& cL[i] <'A'|| cL[i] >'F') //найден не hex-символ break; document.body.style.backgroundColor = (colr.charAt[0] !='#' && i < cL ?'':'#') + colr;
Наверное, это выглядит с первого взгляда сложно, но уже не вызывает отторжения из-за примитивности. Иначе, получается, что мы применяем новейшие технологии сборки, а выразить в коде дружественный интерфейс не в состоянии. Уже потом мы сможем оформить свои пожелания в более совершенном коде, придумать для своих кодов не такой примитивный loadScript и читатель якорей, написать всё это в кофе-скрипте и хранить в своей библиотеке сборки. Ведь к сборкам проектов мы приходим от желания не соглашаться на компромиссы примитивности и просто отображать сложную логику абстракций.
Вариант 1: Closure Compiler
Гугловский Closure Compiler — это инструмент оптимизации JavaScript. Он анализирует код, удаляет ненужные кусочки, а оставшееся — минифицирует. Кроме того, может генерировать Source Map.
Делаем следующие шаги для создания оптимизированной версии скрипта:
- Скачиваем новейший Closure Compiler;
- Кладём файл
compiler.jar
в каталог со скриптами; - В командной строке переходим в каталог "
scripts/
" и выполняем команду, чтобы создать оптимизированный и готовый к выполнению в production файлscript.closure.js
java -jar compiler.jar --js script.js --js_output_file script.closure.js
- Убеждаемся, что
index.html
связан с созданным файлом, раскомментировав «Option A».
![](https://habrastorage.org/files/6e5/f1b/aea/6e5f1baeae7b421e88c605e874179670.png)
Когда мы открываем
index.html
в браузере и смотрим панель Source в инструментах разработчика, имеется ссылка только на оптимизированную версию скрипта script.closure.js
; у нас нет способа связи с оригинальным файлом кодов с нужными отступами. Теперь создадим файл карты кодов выполнением следующей команды в каталоге скриптов:java -jar compiler.jar --js script.js --create_source_map script.closure.js.map --source_map_format=V3 --js_output_file script.closure.js
Обратите внимание, что Closure Compiler использует 2 варианта —
--create_source_map
and --source_map_format
, чтобы создать файл карты script.closure.js.map
с Source Map версии 3. Но и это не всё. Чтобы увидеть эффект, добавьте URL исходников к концу скомпилированного файла script.closure.js
, чтобы он содержал данные о расположении их.//@ sourceMappingURL=script.closure.js.map
Теперь просмотр скриптов в браузере через панель разработчика покажет оба файла — оригинал и оптимизированный
script.closure.js
. Хотя браузер использует оптимизированный файл, Source Map позволяет связать его с исходным кодом.Попробуйте отладку с точками останова. Наблюдаемые выражения и переменные пока недоступны при просмотре исходников. Будем надеяться, что в будущем они появятся!
![](https://habrastorage.org/files/d44/bbd/5d1/d44bbd5d1e3a4e21ada5371846a96e2d.png)
Кириллические пользователи имеют счатье заметить и другой косяк, даже два: один в браузере, другой — в компиляторе. Браузер не отображает символы UTF-8 в файле, подгруженном по маппингу:
Компилятор — и того хуже: кириллические символы считает ошибкой, поэтому их надо удалить перед компиляцией (если это возможно).
Вариант 2: Задача GruntJS для JSMin
Если вы уже используете Grunt.js для сборки проектов, то он сейчас пригодится для кодовых карт из программы JSMin. Код будет не только минифицирован, но также будет создана карта кодов. (Надо вспомнить, что работа
Grunt
версии 0.4 отличается от описываемой в статье версии 0.3. --прим.перев.)Шаги показывают, как создать оптимизированную версию с плагином
JSMin
с помощью Grunt
.1. Установите
Grunt
и запустите (альтернативное свежее описание) в nodeJS gruntfile
под названием grunt.js
, размещённый в корне каталога "start/
".$ npm install -g grunt
$ npm view grunt version
npm http GET https://registry.npmjs.org/grunt
npm http 200 https://registry.npmjs.org/grunt
0.3.17
$ grunt init:gruntfile
Как работать с Grunt 0.4.x
Если у вас установлена старая версия, но вы хотите обновить её до 0.4.x, то процесс установки будет другим. Прежде всего, удалите старую версию Grunt 0.3.x (если была установлена как глобальная).
npm uninstall -g grunt
Ознакомимся подробнее с установкой задач в Grunt 0.4, так как это надолго будет одним из основных инструментов сборки.
Теперь модуль Grunt в новой версии разделён на несколько модулей — ядро и плагины, чтобы вынести все коды приложений из ядра. В установке участвуют несколько модулей.
Установим интерфейс командной строки как глобальный модуль grunt-cli.
npm install -g grunt-cli
Для запуска задач в проектах этого недостаточно — в каждом проекте нужно описать задачи в файле Gruntfile. Если раньше он назывался grunt.js, то в новой версии — Gruntfile.js или Gruntfile.coffee. Второй необходимый файл в корне проекта — это package.json со списком зависимостей, использующийся в npm (Node.js package manager).
В каждой задаче в папке проекта инсталлируется локальный модуль grunt.
Поэтому зайдём в командной строке в папку «start/» и выполним там указанную команду. Как и в 0.3.x-версии, появится папка node_modules и в ней — папка модуля grunt.npm install grunt
Разбрасывание основного кода по проектам сделано с целью возможности запуска разных версий сбрщика на одном компьютере. grunt-cli — всего лишь оболочка, запускающая команду в нужной папке проекта. ( gruntjs.com/getting-started )
Далее, в корне проекта («start/») готовимGruntfile.js
иpackage.json
.package.json
будет связан с вашим проектом и в нём описываются зависимости — потребности в плагинах сборщика. Для нашего проекта напишем:
{ "name": "colors", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.1", "grunt-jsmin-sourcemap": "~1.5.6" } }
Вместо последующего пункта 2 для версии 0.3.х понадобится выполнить
, чтобы подтянуть все зависимости изnpm install grunt --save-dev
package.json
.
2. (Для версии 0.3.х). Установите плагин grunt-jsmin-sourcemap. При этом будет создан каталог
node_modules/grunt-jsmin-sourcemap
.$ npm install grunt-jsmin-sourcemap
3. Отредактируйте созданный
grunt.js
(для версии 0.4 — создайте Gruntfile.js
в «start/») так, чтобы он содержал только задачу jsmin-sourcemap
— будем поступать максимально просто:module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-jsmin-sourcemap');
grunt.initConfig({
'jsmin-sourcemap': {
all: {
src: ['scripts/script.js'],
dest: 'scripts/script.jsmin-grunt.js',
destMap: 'scripts/script.jsmin-grunt.js.map'
}
}
});
grunt.registerTask('default', 'jsmin-sourcemap');
};
4. Вернитесь к командной строке и запустите grunt:
E:\Projects\nodeJS\SourceMaps101\start> grunt
Это выполнит задачу jsmin-sourcemap как задачу по умолчанию, сформулированную в файле
grunt.js
(или Gruntfile.js
). В случае успешного результата:Running "jsmin-sourcemap:all" (jsmin-sourcemap) task
Done, without errors.
Далее, будем складывать результаты выполнения в каталог complete-ru, чтобы отличать результаты автора от своих, которые будут различны в основном из-за новой версии Grunt. Это поможет сверить ваши результаты с теми проверенными, что получены на Windows при запуске примеров. --прим.перев.
5. Убедитесь, что в созданном файле Source Map script.jsmin-grunt.js.map прописан файл исходников:
"sources":["script.js"]
.(На самом деле там прописался
"sources":["scripts/script.js"]
, поэтому следует руками подправить. — прим.перев.)6. Раскомментируйте
Option B
, чтобы подключить созданный файл script.grunt-jsmin.js к index.html, и откройте его в браузере. (Модифицированный файл index-ru.html достаточно вызвать с якорем: localhost/index-ru.html#option=jsmin. — прим.перев.)
В этом примере у нас тоже получился маппинг исходного файла — не зря мы продирались сквозь инсталляцию сборщика. Дальше будет легче, основной инструмент — у нас в кармане.
Как видно и здесь мы наблюдаем косячки сборки, которые затем, если использовать — придётся тексты подправлять серверными скриптами и версию за версией следить за исправлениями. Такая она — разработка с инструментами на ранних стадиях готовности, при этом, очень востребованная рынком.
С
Grunt
и плагином jsmin-sourcemap
процесс сборки создаёт 2 файла: оптимизированный скрипт со ссылкой на маппинг-файл в конце и сам файл карты кодов. Аналогично прежнему варианту, для просмотра исходников понадобятся оба файла.![](https://habrastorage.org/files/f21/9d5/1db/f219d51db764412f815ef1878b81e58e.png)
Вариант 3: UglifyJS
UglifyJS2 — другой оптимизатор-компрессор JS. Как и в 2 прежних случаях, создаются оптимизированный файл скрипта, добавляется URL кодовой карты и сам файл карты, содержащий соответствия между сжатыми и исходными операторами JavaScript. Для использования выполните в каталоге "
start
":1. Инсталлируйте модуль uglify-js (создасстся каталог
nocde_module/uglify-js
):$ npm install uglify-js -g
$ npm view uglify-js version
2.2.3
$ cd scripts/
![](https://habrastorage.org/getpro/habr/post_images/9ec/85e/dd4/9ec85edd4af6df2dca01191b0d8490b1.png)
2. В каталоге “
scripts
” выполним команду создания оптимизированной версии и карты:uglifyjs --source-map script.uglify.js.map --output script.uglify.js script.js
(На этот раз — никакого шаманства руками, всё работает.)
3. В
index.html
раскомментируйте вариант «Option C».![](https://habrastorage.org/files/88a/36d/7f8/88a36d7f808c404c8460d29f470c3243.png)
Вариант 4: CoffeeScript Redux
Так как к моменту написания статьи оригинальная сборка Coffescript от Джереми Ашкенаса не поддерживала меппинг, был использован клон, работающий с меппингом. В версии Coffescript 1.6.1+ можно использовать оригинальный язык (что, впрочем, не уменьшает других достоинств клона).
Клон этот, кстати, успешно собрал заявленные как цель 12 тыс $ на Кикстартере на дальнейшее развитие.
В первых 3 вариантах требовался только 1 шаг оптимизации. Для языков типа CoffeeScript нужно 2 шага: из CoffeeScript в JavaScript, а затем — в оптимизированный JS. Рассмотрим, как создать многоуровневую кодовую карту — из CoffeeScript и из компилятора CoffeeScript Redux (потому что исходный Coffeescript не поддерживал карт до версии 1.6.1 — прим. перев.).
Шаг 1: из CoffeeScript в простой JavaScript
Перейдите в каталог "
start
" в командной строке. В следующих шагах будем создавать файл соответствий между оптимизированным и файлом исходных кодов.1. Установим CoffeeScript с опцией -g возможности глобального вызова.
2. Компилируем
script.coffee.coffee
в простой JS:$ coffee -c scripts/script.coffee.coffee
3. Установим CoffeeScript Redux:
$ git clone https://github.com/michaelficarra/CoffeeScriptRedux.git coffee-redux
$ cd coffee-redux
$ npm install
$ make -j test
$ cd ..
4. Создадим файл маппинга
script.coffee.js.map
, описывающего соответствия между простым JS и исходным CoffeeScript.$ coffee-redux/bin/coffee --source-map -i scripts/script.coffee.coffee > scripts/script.coffee.js.map
5. Убедитесь, что в самом конце файла
script.coffee.js
есть URL-адрес карты кодов://@ sourceMappingURL=script.coffee.js.map
6. Убедитесь, что файл
script.coffee.js.map
имеет правильную ссылку на файл:"file":"script.coffee.coffee", and source file as "sources":["script.coffee.coffee"]
Работа с Coffeescript
Сделаем вместо работы с клоном кофе-скрипта пример с оригинальным компилятором.
Пункты 1 и 2 — остаются без изменений.
Пункт 3 — пропускаем.
4.
coffee -o script.c -cm script.coffee.coffee
("-cm" — это сокращённые параметры "--compile" и "--map".)
5. Косяки.
C созданием выходного файла — сразу пара багов. 1) файл script.coffee.js не создаётся — вместо него — script.js, затирая вариант из первых примеров. Поэтому создаём файл в отдельном каталоге (способа создать файл с другим именем в рамках одной команды не существует, если не рассматривать потоки в ОС); 2) если каталога нет, создаётся «левый» пустой каталог "/-p/" наряду с требуемым.
Для проверки путей стоит запустить этот промежуточный результат, который будет выглядеть как 6-й пример — несжатый coffeescript, и проверит правильность путей в нём.
Если создаём карту кодов одной командой (а не двумя раздельными), то в конце компилированного файла имеется комментарий вида
Оказалось, что в Хроме читается комментарий и такого вида./* //@ sourceMappingURL=script.map */
И «file»: «script.js» и прочие пути в карте кодов тоже менять не понадобилось. Там находится:
"file": "script.js", "sourceRoot": "..", "sources": [ "script.coffee.coffee" ],
Для запуска заранее выбрали такое странное имя каталога, script.c, чтобы он хорошо лёг в ранее построенный скрипт.
var lHash = location.hash.substr(1).split('='); if(lHash && lHash.length ==2 && lHash[0] =='option') var optionName = lHash[1]; if(optionName && !parseInt(optionName)) optionName = {closure:1,jsmin:2,uglifyjs:3,coffeescript:4,typescript:5,'coff':6}[optionName.toLowerCase()]; console.log(optionName); optionName = optionName ||0; var loadScript; (loadScript = function(i){ var scr = document.createElement('SCRIPT'); scr.setAttribute('type', 'application/javascript'); scr.src ='scripts/script.'+ ('|closure|jsmin-grunt|uglify|coffee.min|typescript.min|c/script'.split('|')[i]) +(i?'.':'') +'js'; document.getElementsByTagName('head')[0].appendChild(scr); })(optionName);
При параметре 6 илиcoff
будет читаться скрипт из путиscripts/script.c/script.js
. Видим, что всё работает без заплаток, несмотря на создание промежуточного файла в каталоге. Хорошая работа автора компилятора!
Так выглядит кофескрипт в отладке Хрома.
Видно, что Хром всё так же совершенно не понимает utf-8. Установкаscr.setAttribute('charset', 'utf-8');
тоже не помогает.
Шаг 2: из простого JavaScript в минифицированный JS
1. Наконец, используем UglifyJS, чтобы сжать JS и создать кодовую карту. На этот раз сборщик примет кодовую карту от CoffeeScript, чтобы мы могли добраться до исходных кодов. Выполните команду в "
scripts
":$ cd scripts/
$ uglifyjs script.coffee.js -o script.coffee.min.js --source-map script.coffee.min.js.map --in-source-map script.coffee.js.map
Для нашей ветки примеров вид команды —
uglifyjs script.c/script.js -o script.coffee.min.js --source-map script.coffee.min.js.map --in-source-map script.c/script.map
2. Убедитесь, что файл карты кодов имеет правильную ссылку вида
"file":"script.coffee.min.js"
… и правильные ссылки на исходные коды вида
"sources":["script.coffee.coffee"]
![](https://habrastorage.org/files/11a/274/8a1/11a2748a1edc4d54b3cb41616c6fae1f.png)
Пишем в адресной строке
http://localhost/#option=coffeescript
… И видим, что с путём в файле творится неладное."sources":["script.coffee.coffee"]
должен работать, но не заработал. Но удалось увидеть исходный файл, написав (понадобилось переоткрыть браузер)
"sources":["/scripts/script.coffee.coffee"]
Всё же, сказались усложнённые пути с каталогомscript.c
, и минификатор в связке заработал не так, править пришлось, и эта правка больше похожа на хак сырого продукта.
Вариант 5: TypeScript
TypeScript, как и CoffeeScript, тоже требует 2 этапа: TypeScript -> простой JavaScript -> минифицированный JavaScript. Поскольку скрипт использует плагин jQuery, нужно будет 2 файла TypeScript с именами
script.typescript.ts
и jquery.d.ts
.Установка Typescript:
npm install -g typescript
Шаг 1: из TypeScript в простой JavaScript
Перейдите в каталог «scripts» в режиме командной строки и выполните:
$ tsc script.typescript.ts -sourcemap
Команда создаст файл
script.typescript.js
со ссылкой в конце://@ sourceMappingURL=script.typescript.js.map
И в той же команде создаётся файл карты script.typescript.js.map
.Crhbgn пожаловался на несоответствие некоторых параметров для jQuery и для одного — в нашем коде:
/script.typescript.ts(7,8): The property 'keyCode' does not exist on value of type 'JQueryEventObject'
Но работу принял; файл, который фактически Javascript, обработал.
Чтобы видеть изменения исходных кодов, требуется очистка кеша браузера.
Шаг 2: из простого JavaScript в минифицированный JS
Как и для CoffeweScript, следующий шаг использует UglifyJS:
$ uglifyjs script.typescript.js -o script.typescript.min.js --source-map script.typescript.min.js.map --in-source-map script.typescript.js.map
Убедитесь, что ссылки в
index.html
указывают на правильный файл скрипта: scripts/script.typescript.min.js
и откройте его в браузере.![](https://habrastorage.org/files/21d/754/199/21d7541990274f4da738d23d725aeceb.png)
Ошибок, связанных с компилятором и минификатором, на этом простом коде замечено не было. Исходные коды и меппинг работают без ручных правок служебных файлов.
Карты кодов для SASS
Кроме JavaScript, Chrome в настоящее время поддерживает SASS и SCSS для карт кодов. Для меппинга SASS давайте изменим некоторые настройки в Хроме и затем скомпилируем SASS в CSS с отладочными параметрами.
1. Перед изменением каких-либо настроек обратите внимание, что при наблюдении элемента из окна инструментов разработчика будем видеть только ссылку на CSS. Это не то, что нужно.
![](https://habrastorage.org/files/358/e11/2c8/358e112c804d4b5db780acbb7bc7c30c.png)
2. Заходим в chrome://flags/.
3. Устанавливаем «Enable Developer Tools experiments» (в русской версии Хрома — «Включить экспериментальные инструменты разработчика»).
![](https://habrastorage.org/files/188/ede/2b7/188ede2b757d4ac58a51c9fb85fb9419.png)
В Windows:
![](https://habrastorage.org/getpro/habr/post_images/0eb/966/77c/0eb96677cd32ba523a4df863a2b074cf.png)
4. Открываем
Dev Tools -> Setting -> Experiments -> Check “Support for SASS”
.![](https://habrastorage.org/files/2b9/efc/d29/2b9efcd295b448d5a453d9127cd3350b.png)
В Windows:
Настройки (☰) -> Инструменты -> Инструменты разработчика -> Settings (⏣ в правом нижнем углу) -> Experiments -> Support for Sass.
![](https://habrastorage.org/getpro/habr/post_images/189/80b/df7/18980bdf774bcf2fab13caa267b34e83.png)
5. Компилируем SASS с такими параметрами отладки в каталоге "
styles
" в командной строке. Этим будет предваряться каждый набор правил с @media -sass-debug-info
$ cd styles/
$ sass --debug-info --watch style.sass:style.css
6. Убедитесь, что окно Developer Tools переоткрыто и страница перезагружена.
7. Теперь, когда проверяем элемент в Dev.Tools, будем видеть доступ к SASS-файлу.
![](https://habrastorage.org/files/bf8/c92/2a3/bf8c922a33734c028c30c70e0e71c3b9.png)
Кроме простого просмотра SASS, если запущен LiveReload в фоне, то при изменении SASS-файла страница тоже будет изменяться.
Теперь — откроем проект в Firefox и посмотрим через Firebug. В нём тоже будет доступен просмотр SASS-файла.
![](https://habrastorage.org/files/b2a/d07/871/b2ad078715f44abb9b41a2b52c10af5d.png)
Информация о кодовых картах
Если мы посмотрим любой
*.map
файл, он будет содержать сопоставление информации между исходным файлом и результирующим. Структура, как правило, содержится в формате JSON по спецификации карт версии 3. Обычно, имеется 5 свойств:1. version: версия карты (обычно 3).
2. file: имя выходного файла.
3. sources: имя исходного файла.
4. names: символы, используемые для соответствий.
5. mappings: данные соответствий.
![](https://habrastorage.org/files/02c/fc0/9e6/02cfc09e6f594ae69e51d3df65b39bfc.png)
Дополнительные ссылки
Карты кодов всё ещё находятся в стадии активной разработки, но уже есть некоторые заметные ресурсы в Сети. Обязательно посмотрите такие ссылки, чтобы узнать больше.
- Введение в JavaScript Source Maps by Ryan Seddon, HTML5 Rocks, 21 марта 2012; Перевод.
- The Breakpoint Episode 3: JavaScript Source Maps by the Google Developer Team
- The Breakpoint Episode 2: SASS Source Maps by the Google Developer Team
- Source Maps wiki on languages, tools, articles on Source Maps
- Multi Level Source Maps with CoffeeScript and TypeScript by Ryan Seddon
- Source Maps Version 3 proposal
Заключение
Надеюсь, что практика использования нескольких компиляторов показала потенциал карт кодов. Хотя функциональность сейчас ограничена, в будущем есть основания ожидать возможности полноценной отладки, в том числе, в виде доступа к переменным и выражениям.
![]()
Автор: Sayanee Basu, независимый разработчик из Сингапура. В её профиле описано знание технологий Ruby и связанных с ним сахарных метаязыков. Отсюда — интерес к сырцовым картам.
Можно согласиться с автором, что «функциональность ограничена» и сказать больше — почти в каждом примере присутствовали баги с путями к файлам. Имеем состояние сырой технологии; отдалённая аналогия — примерно так было с nodeJS порядка года назад. Но объём доработок не такой большой, вопрос не года, а месяцев, и что вселяет надежду — часть багов лежит в подконтрольных кодах, написанных на nodeJS. При большом желании там можно разобраться. Но уровень гиковости для работы с этой технологией должен быть таким же, как у тех, кто ставит альфа-версии браузеров, не для развлечения, а для дела.
(Следующие вести с полей будут видимо, через пару месяцев про Firefox с его умением работать со всем этим устаканивающимся хозяйством.)
Нужно ли с этим работать сейчас? Если есть большое желание перейти на Coffeescript, то время для него уже настало. Уже сейчас можно получать неоценимый опыт отладки проектов, когда раньше приходилось работать фактически с 2 языками, помня, что отлаживать придётся JS.
Если уже используется Grunt, то для того, чтобы перейти на Кофе и SASS — сейчас дистанция вхождения стала ещё короче. Но, судя даже по примерам, надо быть готовым с головой окунуться во весь стек технологий, ища решение при выявлении багов сборки. Хорошо видно, что баги будут активно исправляться — через поддержку надстроечных языков проходит вектор интересов нескольких крупных игроков рынка, которые просто так недоработки не оставят, потому что чувствуется дыхание догоняющих, а финиш близок.
Если вы пройдёте примеры вместе с автором, или ещё лучше, затем устанОвите коды из своих проектов, проинсталлируете необходимые модули nodeJS, это будет хорошим шагом по освоению технологий фронтенд-сборки и отладки приложений.
Примеры, которые использовались в статье и были проверены на Windows + nodeJS.
1) Using Source Maps with TypeScript, Aaron Powell, Oct 3 2012;
2) github.com/mozilla/source-map — This is a library to generate and consume the source map format.
3) Happy debugging with JavaScript source maps by James Allardice, 25 January 2013.
4) bower.io — альтернативный сборщик от Twitter.
5) kevinpelgrims.com/blog/2011/12/28/building-coffeescript-with-sublime-on-windows
6) sourcemap.litcoffee.
7) github.com/evanw/node-source-map-support
8) Переводы, привязанные к источнику (2013-05)