Отладка JavaScript в производственной среде с помощью карт источников

Отладка JavaScript в производственной среде с помощью карт источников

От автора: для чего нужна отладка JavaScript? В наши дни код, который вы используете для написания приложения, обычно не тот же код, который был развернут в производственной среде и интерпретируется браузерами. Возможно, вы пишете исходный код на языке, который «компилируется» в JavaScript, например CoffeeScript, TypeScript или в последней версии стандарта JavaScript, ECMAScript 2015 (ES6). Или, что еще более вероятно, вы минимизируете свой исходный код, чтобы уменьшить размер файлов развернутых скриптов. Вероятно, вы используете такой инструмент, как UglifyJS или компилятор Google Closure.

Такие инструменты преобразования часто называются транспиляторами — инструментами, которые преобразуют исходный код с одного языка на тот же язык или на другой аналогичный язык высокого уровня. Их вывод представляет собой код с расширением, который, хотя и функционирует в целевой среде (например, совместимый с браузером JavaScript), обычно он мало похож на код, из которого был сгенерирован.

Это представляет проблему: при отладке кода в браузере или проверке треков стека, сгенерированных из-за ошибок в вашем приложении, вы просматриваете переписанный и (обычно) трудночитаемый JavaScript, а не исходный код, который использовался для написания приложения. Это может затруднить отслеживание ошибок JavaScript.

Решение этой проблемы — отличная функция браузера, называемая картами источников. Давайте узнаем об этом больше.

Карты источников

Карты источников — это файлы JSON, содержащие информацию о том, как перевести транспилированный исходный код в оригинальный исходный код. Если вы когда-либо программировали на компилируемом языке, таком как Objective-C, вы можете представить себе исходные карты как версии отладочных символов JavaScript. Вот пример карты источников:

{ version : 3, file: "app.min.js", sourceRoot : "", sources: ["foo.js", "bar.js"], names: ["src", "maps", "are", "fun"], mappings: "AAgBC,SAAQ,CAAEA"
}

Вам, вероятно, никогда не придется создавать эти файлы самостоятельно, но не повредит, если вы будете понимать, что они содержат:

version: версия спецификации исходной карты, которую этот файл представляет (должно быть «3»)

file: сгенерированное имя файла, с которым связана эта исходная карта

sourceRoot: корень URL-адреса, для которого все источники являются относительными (необязательно)

sources: массив URL-адресов к исходным файлам

names: массив имен переменных / методов, найденных в вашем коде

mappings: фактические сопоставления исходного кода, представленные в качестве значений VLQ в кодировке base64

Если похоже, что это трудно запомнить, не волнуйтесь. Мы объясним, как использовать инструменты для создания этих файлов.

sourceMappingURL

Чтобы указать браузерам, что для транспилированного файла доступна карта источников, в конец этого файла нужно добавить директиву sourceMappingURL:

// app.min.js
$(function () { // your application ...
});
//# sourceMappingURL=/path/to/app.min.js.map

Когда современные браузеры видят директиву sourceMappingURL, они загружают исходную карту из предоставленного местоположения и используют информацию, чтобы приложить к выполняемому клиентскому коду исходный код. Вот как это выглядит, когда мы переходим к исходному ES6 + JSX коду Sentry в Firefox с использованием карт источников (обратите внимание: браузеры загружают и используют исходные карты, когда открыты инструменты разработчика. Для обычных пользователей это не влияет на производительность):

Отладка JavaScript в производственной среде с помощью карт источников

Создание карты источников

Хорошо, теперь мы в общих чертах знаем, как работают карты источников, и как заставить браузер загружать и использовать их. Но как мы можем фактически генерировать их и ссылаться на них из транспилируемых файлов?

Хорошие новости! В основном каждый современный транспилятор JavaScript имеет параметр командной строки для создания связанной карты источников. Давайте рассмотрим несколько общих вариантов.

UglifyJS

UglifyJS — популярный инструмент для минимизации исходного кода в производственной среде. Он может значительно уменьшить размер файлов, устраняя пробелы, переписывая имена переменных, удаляя ветви мертвого кода и т. д.

Если вы используете UglifyJS для минимизации исходного кода, следующая команда из UglifyJS 3.3.x дополнительно генерирует карту источников, переводящую минимизированный код обратно в оригинальный исходный код:

$ uglifyjs app.js -o app.min.js --source-map

Если вы посмотрите на сгенерированный выходной файл app.min.js, вы заметите, что конечная строка включает директиву sourceMappingURL, указывающую на нашу вновь созданную карту источников.

//# sourceMappingURL=app.min.js.map

Обратите внимание, что это относительный URL. Чтобы браузер загружал связанную карту источников, она должна загружаться и обслуживаться из того же целевого каталога, что и Uglified file, app.min.js. Это означает, что если app.min.js будет отправлен из http://example.org/static/app.min.js, вам также должна быть доступна карта источников из http://example.org/static/app.min. js.map.

Относительные URL-адреса — это не единственный способ указать sourceMappingURL. Вы можете дать Uglify абсолютный URL-адрес с помощью опции -source-map-url <url>. Или вы даже можете включить всю карту источников в строку, хотя это не рекомендуется. Ознакомьтесь с параметрами командной строки Uglify для получения дополнительной информации.

Webpack

Webpack — это мощный инструмент сборки, который преобразует и связывает модули JavaScript в файлы, пригодные для работы в браузере. Сам проект Sentry использует Webpack (наряду с Babel) для сборки и перевода своей кодовой базы ES6 + JSX в совместимый с браузерами JavaScript.

Создать карту источников с помощью Webpack очень просто. В Webpack 4 укажите свойство devtool в файле конфигурации:

// webpack.config.js
module.exports = { // ... entry: { "app": "src/app.js" }, output: { path: path.join(__dirname, 'dist'), filename: "[name].js", sourceMapFilename: "[name].js.map" }, devtool: "source-map" // ...
};

Теперь, когда вы запускаете программу командной строки, Webpack собирает ваши файлы, генерирует карту источников и ссылается на эту карту во встроенном файле JavaScript через директиву sourceMappingUrl.

Закрытые карты источников

До этого момента все наши примеры предполагали, что карты источников общедоступны и обслуживаются с того же сервера, что и ваш исполняемый код JavaScript. В этом случае любой разработчик может использовать ваши карты источников для получения оригинального исходного кода.

Чтобы предотвратить это, вместо предоставления общедоступного sourceMappingURL вы можете обслуживать карты источников с сервера, доступного только вашей команде разработчиков. Примером может служить сервер, доступный только из VPN вашей компании.

//# sourceMappingURL: http://company.intranet/app/static/app.min.js.map

Когда участник, не являющийся членом команды, посещает ваше приложение с открытыми инструментами разработчика, он попытается загрузить эту карту источников, но получит ошибку HTTP 404 (или 403), и карта источников не будет применяться.

Карты источников и Sentry

Если вы используете Sentry для отслеживания исключений в клиентских JavaScript-приложениях, у нас есть хорошие новости! Sentry автоматически извлекает и применяет карты источников для отслеживания стеков, генерируемых ошибками. Это означает, что вы увидите оригинальный исходный код, а не минимизированный и / или преобразованный. Вот как выглядит трассировка стека неминимизированного кода в Sentry:

Отладка JavaScript в производственной среде с помощью карт источников

В принципе, если вы выполнили действия, описанные в этой статье, и теперь развернутая база сгенерировала, карты источников и транспилированные файлы загружены с помощью директив sourceMappingURL, указывающих на эти карты источников, вам больше ничего не нужно делать. Sentry сделает все остальное.

Sentry и оффлайн карты источников

Альтернативно, вместо того, чтобы не размещать карты источников самим, вы можете загрузить их прямо в Sentry. Для чего это делать? Есть несколько причин:

В случае, если Sentry с трудом достигает ваших серверов (например, карты источников размещаются на VPN)

Преодоление латентности — карты источников будут находиться внутри Sentry до того, как будет введено исключение

Вы разрабатываете приложение, которое запускается изначально на устройстве (например, при использовании React Native или PhoneGap, исходный код / карты недоступны через Интернет)

Чтобы избежать несоответствий версий, когда выбранная карта источников не соответствует коду, в котором была введена ошибка

Заключение

Вы только что узнали, как карты источников могут помочь вам, сделав более простой отладку вашего транспилированного кода в производственной среде. Поскольку ваши инструменты сборки, вероятно, уже поддерживают генерацию карт источников, для настройки не потребуется очень много времени. Вот и все! Успехов в мониторинге ошибок.

Автор: Ryan Goldman

Источник: https://scotch.io/

Редакция: Команда webformyself.