Я начинаю проект с помощью 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 (никогда не публиковавшегося) и потраченных часов на возню с файлами конфигурации, обмен мнениями заставил меня кардинально изменить только две вещи.

  1. Избавиться от Babel в индивидуальном порядке. Компилируйте файлы прямо из src/ в dist/, используя Weback с babel-loader
  2. Подскажите отладчику, где искать карты

Для всех, кому интересно, конфигурация Webpack выглядит так, а окончательная launch.json конфигурация отладчика выглядит так.

Хммм. А теперь я забыл, что отлаживал.