Практический пример: улучшение угловой отладки с помощью DevTools

Улучшенный опыт отладки

В течение последних нескольких месяцев команда Chrome DevTools сотрудничала с командой Angular, чтобы улучшить возможности отладки в Chrome DevTools. Люди из обеих команд работали вместе и предприняли шаги, чтобы дать разработчикам возможность отлаживать и профилировать веб-приложения с точки зрения автора : с точки зрения исходного языка и структуры проекта, с доступом к информации, которая им знакома и актуальна.

В этом посте мы заглянем под капот и увидим, какие изменения в Angular и Chrome DevTools потребовались для достижения этой цели. Несмотря на то, что некоторые из этих изменений демонстрируются в Angular, их можно применить и к другим платформам. Команда Chrome DevTools призывает другие платформы использовать новые консольные API и точки расширения карты исходного кода, чтобы они также могли предложить своим пользователям более удобные возможности отладки.

Игнорировать код листинга

При отладке приложений с помощью Chrome DevTools авторы обычно хотят видеть только свой код , а не код лежащей под ним платформы или какую-то зависимость, спрятанную в папке node_modules .

Чтобы добиться этого, команда DevTools представила расширение исходных карт под названием x_google_ignoreList . Это расширение используется для идентификации сторонних источников, таких как код платформы или код, созданный сборщиком. Когда фреймворк использует это расширение, авторы теперь автоматически избегают кода, который они не хотят видеть или выполнять , без необходимости предварительно настраивать его вручную .

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

Анимированный GIF-файл, показывающий DevTools до и после. Обратите внимание, как на изображении ниже DevTools отображает авторский код в дереве, больше не предлагает никаких файлов платформы в меню «Быстрое открытие» и показывает гораздо более чистую трассировку стека справа.

Расширение исходной карты x_google_ignoreList

В картах источников новое поле x_google_ignoreList ссылается на массив sources и перечисляет индексы всех известных сторонних источников в этой карте источников. При анализе исходной карты Chrome DevTools будет использовать ее, чтобы определить, какие разделы кода следует исключить из списка игнорируемых.

Ниже приведена исходная карта сгенерированного файла out.js Существует два исходных sources , которые способствовали созданию выходного файла: foo.js и lib.js Первое — это то, что написал разработчик веб-сайта, а второе — это фреймворк, который они использовали.

{
  "version" : 3,
  "file": "out.js",
  "sourceRoot": "",
  "sources": ["foo.js", "lib.js"],
  "sourcesContent": ["...", "..."],
  "names": ["src", "maps", "are", "fun"],
  "mappings": "A,AAAB;;ABCDE;"
}

sourcesContent включен в оба этих исходных источника, и Chrome DevTools по умолчанию отображает эти файлы в отладчике:

  • Как файлы в дереве источников.
  • Как результат в диалоговом окне быстрого открытия.
  • В качестве сопоставленных местоположений кадров вызова в трассировке стека ошибок во время паузы в точке останова и при пошаговом выполнении.

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

{
  ...
  "sources": ["foo.js", "lib.js"],
  "x_google_ignoreList": [1],
  ...
}

Новое поле x_google_ignoreList содержит единственный индекс, ссылающийся на массив sources : 1. Он указывает, что регионы, сопоставленные с lib.js на самом деле являются сторонним кодом, который должен автоматически добавляться в список игнорирования.

В более сложном примере, показанном ниже, индексы 2, 4 и 5 указывают, что регионы, сопоставленные с lib1.ts , lib2.coffee и hmr.js , являются сторонним кодом, который должен быть автоматически добавлен в список игнорирования.

{
  ...
  "sources": ["foo.html", "bar.css", "lib1.ts", "baz.js", "lib2.coffee", "hmr.js"],
  "x_google_ignoreList": [2, 4, 5],
  ...
}

Если вы разработчик фреймворка или сборщика, убедитесь, что карты исходного кода, созданные в процессе сборки, включают это поле, чтобы использовать эти новые возможности в Chrome DevTools.

x_google_ignoreList в Angular

Начиная с Angular v14.1.0 , содержимое папок node_modules и webpack помечено как «игнорировать» .

Это было достигнуто за счет изменения angular-cli путем создания плагина, который подключается к модулю Compiler веб-пакета.

Плагин веб-пакета , созданный нашими инженерами, подключается к этапу PROCESS_ASSETS_STAGE_DEV_TOOLING и заполняет поле x_google_ignoreList в исходных картах для конечных ресурсов, которые генерирует веб-пакет и загружает браузер.

const map = JSON.parse(mapContent) as SourceMap;
const ignoreList = [];

for (const [index, path] of map.sources.entries()) {
  if (path.includes('/node_modules/') || path.startsWith('webpack/')) {
    ignoreList.push(index);
  }
}

map[`x_google_ignoreList`] = ignoreList;
compilation.updateAsset(name, new RawSource(JSON.stringify(map)));

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

Трассировки стека отвечают на вопрос «как я сюда попал» , но зачастую это происходит с точки зрения машины, а не обязательно что-то, что соответствует точке зрения разработчика или его ментальной модели среды выполнения приложения. Это особенно верно, когда некоторые операции запланированы на асинхронное выполнение позже: все равно может быть интересно узнать «основную причину» или сторону планирования таких операций, но это именно то, что не будет частью асинхронной трассировки стека.

В V8 имеется внутренний механизм отслеживания таких асинхронных задач, когда используются стандартные примитивы планирования браузера, такие как setTimeout . В таких случаях это делается по умолчанию, поэтому разработчики уже могут это проверить! Но в более сложных проектах все не так просто, особенно при использовании платформы с более продвинутыми механизмами планирования — например, той, которая выполняет отслеживание зон, постановку настраиваемых задач в очередь или которая разбивает обновления на несколько единиц работы, выполняемых во времени.

Чтобы решить эту проблему, DevTools предоставляет в объекте console механизм под названием «Async Stack Tagged API», который позволяет разработчикам платформы указывать как места, где запланированы операции, так и места их выполнения.

API тегирования асинхронного стека

Без асинхронной маркировки стека трассировки стека для кода, который асинхронно выполняется платформами сложными способами, отображаются без связи с кодом, в котором он был запланирован.