Современная веб-отладка в 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 предлагает рекомендации по тому, как это реализовать.