Современная веб-отладка в Chrome DevTools

Введение

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

Например, компоненты, созданные на основе платформы Angular, создаются на TypeScript с использованием шаблонов HTML. Под капотом Angular CLI и веб-пакет компилируют все в JavaScript и в так называемый пакет , который затем отправляется в браузер.

При отладке или профилировании веб-приложений в DevTools вы в настоящее время можете видеть и отлаживать скомпилированную версию вашего кода, а не код, который вы на самом деле написали. Однако вы, как автор, этого не хотите:

  • Вы не хотите отлаживать минифицированный код JavaScript, вы хотите отлаживать исходный код JavaScript.
  • При использовании TypeScript вам не нужно отлаживать JavaScript, а нужно отлаживать исходный код TypeScript.
  • Когда вы используете шаблоны, такие как Angular, Lit или JSX, вам не всегда нужно отлаживать полученный DOM. Возможно, вам захочется отладить сами компоненты.

В целом, вы, скорее всего, захотите отладить свой собственный код по мере его написания .

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

Давайте взглянем!

Авторский и развернутый код

В настоящее время при навигации по дереву файлов на панели «Источники» вы можете увидеть содержимое скомпилированного (и часто минимизированного) пакета . Это реальные файлы, которые браузер загружает и запускает. DevTools называет это развернутым кодом .

Снимок экрана дерева файлов в Chrome DevTools, показывающий развернутый код.

Это не очень удобно и часто трудно понять. Как автор, вы хотите видеть и отлаживать написанный вами код, а не развернутый код .

Чтобы компенсировать это, теперь вы можете вместо этого отображать в дереве авторский код . Это делает дерево более похожим на исходные файлы, которые вы видите в своей IDE, и эти файлы теперь отделены от развернутого кода .

Снимок экрана дерева файлов в Chrome DevTools, показывающий авторский код.

Чтобы включить эту опцию в Chrome DevTools, перейдите в «Настройки» > «Эксперименты» и установите флажок «Группировать источники в авторские и развернутые деревья» .

Скриншот настроек DevTools.

«Только мой код»

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

Чтобы компенсировать это, в DevTools по умолчанию включена дополнительная настройка: автоматически добавлять известные сторонние скрипты в список игнорирования . Вы можете найти его в DevTools > Настройки > Список игнорирования .

Скриншот настроек DevTools.

Если этот параметр включен, DevTools скрывает любой файл или папку, которые платформа или инструмент сборки пометили как игнорируемые .

Начиная с Angular v14.1.0 , содержимое папок node_modules и webpack помечено как таковое. Таким образом, эти папки, файлы внутри них и другие подобные сторонние артефакты не отображаются в различных местах DevTools.

Вам как автору не нужно ничего делать, чтобы включить это новое поведение. Реализация этого изменения зависит от структуры.

Игнорировать код, указанный в трассировках стека

Единственное место, где эти файлы из списка игнорируемых больше не отображаются, — это трассировки стека. Как автор, вы теперь можете видеть более релевантные трассировки стека .

Снимок экрана: трассировка стека в DevTools.

Если вы хотите просмотреть все кадры вызовов трассировки стека, вы всегда можете нажать ссылку «Показать больше кадров» .

То же самое относится и к стекам вызовов, которые вы видите во время отладки и пошагового выполнения кода . Когда платформы или сборщики сообщают DevTools о сторонних скриптах, DevTools автоматически скрывает все ненужные фреймы вызовов и пропускает любой код из игнорируемого списка во время пошаговой отладки.

Снимок экрана отладчика DevTools Sources во время отладки.

Игнорировать код, указанный в дереве файлов

Чтобы скрыть файлы и папки из списка игнорируемых из дерева файлов авторского кода на панели « Источники », установите флажок «Скрыть код из списка игнорируемых в дереве источников» в разделе « Настройки » > «Эксперименты» в DevTools.

Скриншот настроек DevTools.

В примере проекта Angular папки node_modules и webpack теперь скрыты.

Снимок экрана дерева файлов в Chrome DevTools, показывающий авторский код, но не показывающий node_modules.

Игнорировать код, указанный в меню «Быстрое открытие»

Код из игнорируемого списка не только скрыт из дерева файлов, но также скрыт из меню «Быстрое открытие» ( Control + P (Linux/Windows) или Command + P (Mac) ).

Скриншот DevTools с меню «Быстрое открытие».

Дополнительные улучшения трассировки стека

Уже рассмотрев соответствующие трассировки стека, Chrome DevTools вводит еще больше улучшений в трассировку стека.

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

Когда некоторые операции запланированы на асинхронное выполнение, трассировка стека в DevTools в настоящее время рассказывает лишь часть истории.

Например, вот очень простой планировщик в гипотетическом файле framework.js :

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      tasks.push({ f });
    },

    work() {
      while (tasks.length) {
        const { f } = tasks.shift();
        f();
      }
    },
  };
}

const scheduler = makeScheduler();

function loop() {
  scheduler.work();
  requestAnimationFrame(loop);
};

loop();

… и как разработчик может использовать его в своем коде в файле example.js :

function someTask() {
  console.trace("done!");
}

function businessLogic() {
  scheduler.schedule(someTask);
}

businessLogic();

При добавлении точки останова внутри метода someTask или при проверке трассировки, напечатанной в консоли, вы не увидите никакого упоминания о вызове businessLogic() , который был «основной причиной» этой операции.

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

Трассировка стека некоторого асинхронно выполняемого кода без информации о том, когда он был запланирован.

Благодаря новой функции под названием «Теги асинхронного стека» в конце концов можно рассказать всю историю, связав обе части асинхронного кода вместе.

API Async Stack Tagged представляет новый console метод с именем console.createTask() . Подпись API выглядит следующим образом:

interface Console {
  createTask(name: string): Task;
}

interface Task {
  run<T>(f: () => T): T;
}

Вызов console.createTask() возвращает экземпляр Task , который позже можно использовать для запуска содержимого задачи f .

// Task Creation
const task = console.createTask(name);

// Task Execution
task.run(f);

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

Применительно к функции makeScheduler , указанной выше, код становится следующим:

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      const task = console.createTask(f.name);
      tasks.push({ task, f });
    },

    work() {
      while (tasks.length) {
        const { task, f } = tasks.shift();
        task.run(f); // instead of f();
      }
    },
  };
}

Благодаря этому Chrome DevTools теперь может лучше отображать трассировку стека.

Трассировка стека некоторого асинхронно выполняемого кода с информацией о том, когда он был запланирован.

Обратите внимание, что businessLogic() теперь включен в трассировку стека! Более того, задача имеет знакомое имя someTask вместо общего requestAnimationFrame как раньше.

Фреймы дружеского вызова

При создании проекта фреймворки часто генерируют код из всех видов языков шаблонов, например шаблонов Angular или JSX, которые превращают код, похожий на HTML, в простой JavaScript, который в конечном итоге запускается в браузере. Иногда таким типам сгенерированных функций присваиваются не очень дружелюбные имена — либо однобуквенные имена после их минимизации, либо какие-то неясные или незнакомые имена, даже если это не так.

В примере проекта примером этого является AppComponent_Template_app_button_handleClick_1_listener , который вы видите в трассировке стека.

Снимок экрана трассировки стека с автоматически созданным именем функции.

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

Вам как автору не нужно ничего делать, чтобы включить это новое поведение. Реализация этого изменения зависит от структуры.

Заглядывая вперед

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

Команда Chrome DevTools призывает авторов фреймворков использовать эти новые возможности. Тематическое исследование: Улучшение угловой отладки с помощью DevTools предлагает рекомендации по тому, как это реализовать.