Я начинаю проект с помощью Preact и хотел настроить отладку через отладчик в Visual Studio Code (VSCode, кстати, отличный). Конвейер сборки использует Babel для транспиляции последних функций Javascript и Webpack для компиляции модулей в один файл сборки. Структура каталогов выглядит примерно так (пока не обращайте внимания на файлы .map
, мы перейдем к ним):
├── build │ └── js │ ├── app.js │ ├── app.js.map │ ├── components │ │ ├── calendar.js │ │ └── calendar.js.map │ ├── index.js │ └── index.js.map ├── dist │ ├── app.bundle.js │ ├── app.bundle.js.map │ └── index.html ├── gulpfile.js ├── package.json ├── src │ ├── js │ │ ├── app.js │ │ ├── components │ │ │ └── calendar.js │ │ └── index.js │ ├── pug │ │ └── index.pug │ └── scss │ ├── _grid.scss │ └── timelog.scss └── webpack.config.js
Таким образом, файлы в src
проходят через Babel, получают вывод в каталог build
, а затем Webpack компилирует все из build
и объединяет их в один js
файл в каталоге dist
. Для иллюстрации:
src/js/app.js => babel => build/js/app.js build/js/app.js => webpack => dist/app.bundle.js
Проблема
Я хотел установить точку останова в одном из моих классов React (Calendar
), скажем, в функции render
, чтобы я мог проверить некоторые из проблемных переменных. Поэтому я установил точку останова с помощью VSCode.
На данном этапе я немного не уверен, в каком файле мне следует установить точку останова. Нужно ли это делать в скомпилированном / скомпилированном конечном продукте, поскольку этот код оценивается во время выполнения? В идеале я мог бы указать его в каталоге src
для ясного и быстрого понимания поведения моего компонента. Но как он вообще узнает, что есть точка останова, если он работает dist/app.bundle.js
? (Спойлер: исходные карты)
Иногда в программировании нужно просто попробовать что-то.
Поэтому я поместил точку останова в исходный файл src
и попробовал. Отладчик подключается к экземпляру Chrome, но точка останова неактивна, и код никогда не ломается. Какой сюрприз. Всплывающая подсказка при наведении курсора на точку останова дает нам некоторые подсказки:
Breakpoint ignored because generated code not found (source map problem?).
Исходные карты
Я лишь смутно осознавал, что исходные карты были чем-то особенным, поэтому, очевидно, неправильно их настроил. Я предполагаю, что точка останова должна каким-то образом найти свой путь во время выполнения и, вероятно, для каждого шага в моем процессе сборки, который приводит к новому пакету файловjs
. Итак, мне нужно настроить исходные карты для Babel и Webpack.
Мы добавляем --source-maps
в команду сборки Babel и редактируем конфигурацию Webpack, чтобы включить:
module.exports = { ... devtool: 'source-map', ... }
Это дает нам .map
файлов, которые мы видим в дереве каталогов. Повторный запуск отладчика дает тот же результат. Грустное лицо.
Конфигурация отладчика VSCode
Возможно, отладчик неправильно настроен. Конфигурацию можно найти в launch.json
файле, который вам предоставляет VSCode (его можно найти в каталоге вашего проекта под .vscode/launch.json
, или вы можете открыть его, используя значок шестеренки в правом верхнем углу панели отладки). Я считаю, что могу добавить diagnosticLogging
, чтобы получить дополнительную информацию. Мой launch.json
теперь выглядит примерно так:
{ "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "http://localhost:3000", "sourceMaps": true, "webRoot": "${workspaceRoot}", "diagnosticLogging": true }, { "type": "chrome", "request": "attach", "name": "Attach to Chrome", "port": 9222, "webRoot": "${workspaceRoot}" } ] }
Углубившись в плагин vscode-chrome-debug
, они дают хорошее направление для настройки исходных карт. Итак, какие сопоставления мне нужно указать с помощью sourceMapPathOverrides
? Взглянув на консоль отладки, мы видим следующее:
SourceMap: mapping webpack:///./build/js/index.js => ${workspaceRoot}/dist/build/js/index.js
Это не выглядит правильным. Давайте посмотрим на фактические сопоставления в файлах .map.
Для dist/app.bundle.map.js
у нас есть
"sources":["webpack:///webpack/bootstrap 947e84c9f9233792775c","webpack:///./node_modules/preact/dist/preact.min.js","webpack:///./build/js/index.js","webpack:///./build/js/app.js","webpack:///./build/js/components/calendar.js"]
А что насчет build/app.map.js
?
"sources":["../../src/js/app.js"]
Кажется правильным. Итак, карты есть и указывают в правильном направлении, но отладчик не следит за ними. Должен ли я направлять карты веб-пакетов прямо в каталог src
?
[… Проходит несколько часов]
Ты делаешь это неправильно
Когда я не могу найти примеры (например, сообщения Stackoverflow, проблемы с Github и т. Д.) Людей, у которых были похожие симптомы, это означает, что я делаю что-то очень необычное (то есть неправильно).
Я не могу точно вспомнить, почему я разделил задачи Webpack и Babel. Действительно, у Webpack есть babel-loader
функции, которые сделают все за вас за один раз. Думаю, используя незаметные инструменты, я мог убедиться, что обе версии были самыми последними. Но я думаю, что это действительно слишком усложняет отладку.
Итак, после написания большей части этого сообщения в блоге, работы над лаконично написанным сообщением Stackoverflow (никогда не публиковавшегося) и потраченных часов на возню с файлами конфигурации, обмен мнениями заставил меня кардинально изменить только две вещи.
- Избавиться от Babel в индивидуальном порядке. Компилируйте файлы прямо из
src/
вdist/
, используя Weback сbabel-loader
- Подскажите отладчику, где искать карты
Для всех, кому интересно, конфигурация Webpack выглядит так, а окончательная launch.json
конфигурация отладчика выглядит так.
Хммм. А теперь я забыл, что отлаживал.