Это перевод статьи Мэтта Деслорьерса — «Debugging Node.js in Chrome DevTools», оригинал которой можно найти у него в блоге по этой ссылке.

Этот пост является введением в новый подход разработки, отладки и профилирования Node.js приложений, используя Chrome DevTools.

devtool

Недавно я работал над консольной утилитой devtool, которая запускает Node.js программы внутри Chrome DevTools.

Запись показывает настройку контрольных точек внутри HTTP-сервера.

Настройка контрольных точек HTTP-сервера

Эта утилита построена на Electron, который является смесью возможностей Node.js и Chromium. Эта утилита призвана обеспечить простой интерфейс для отладки, профилирования и разработки Node.js приложений.

Вы можете установить devtool, используя npm:

$ npm install -g devtool

REPL

В некотором смысле, мы можем использовать devtool как замену команде node в консоли. Для примера, можно открыть REPL вот так:

$ devtool

Это запустит новый экземпляр Chrome DevTools с поддержкой всех возможностей Node.js:

Новый экземпляр Chrome DevTools

Мы можем подключать модули Node.js, использовать локальные модули и встроенные, как process.cwd(). Также мы имеем доступ к функциям Chrome DevTools, таким как copy() и table().

Несколько других примеров:

# Запуск скрипта
$ devtool app.js

# Канал контента из файла в process.stdin
$ devtool < audio.mp3

# Канал JavaScript-кода для вычисления
$ browserify index.js | devtool

Разработка

Мы можем использовать devtool для непрерывной разработки любого модуля и приложения, вместо уже существующих утилит вроде nodemon.

$ devtool app.js --watch

Эта команда запустить ваш app.js в консоли Chrome DevTools. С помощью флага --watch мы указываем, чтобы при сохранении файла консоль автоматически перезагружалась.

Автоматическая перезагрузка консоли

Кликаем по ссылке app.js:1, которая приведёт нас на соответствующий файл и строку во вкладке Sources:

Вкладка Sources в Chrome DevTools

Пока открыта вкладка Sources вы можете использовать клавиатурное сокращение Cmd/Ctrl + P для быстрого поиска необходимого модуля. Вы даже можете инспектировать и отлаживать внутренние модули Node.js. Для просмотра модулей можно использовать левую панель.

Просмотр модулей приложения внутри Chrome DevTools

Отладка

Так как мы имеем доступ ко вкладке Sources, то мы можем использовать её для отладки нашего приложения. Вы можете установить контрольные точки и затем перезагрузить отладчик (Cmd/Ctrl + R), или вы можете установить начальную контрольную точку с флагом --break.

$ devtool app.js --break

Контрольные точки в devtool

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

Подсказка

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

Пауза devtool

Профилирование

Другим вариантом применения devtool является профилирование приложений, таких как browserify, gulp и babel.

Здесь мы используем console.profile() — возможность Chrome для профилирования загрузки CPU сборщиком.

var browserify = require('browserify');

// Начало DevTools профилирования...
console.profile('build');

// Сборка какого-нибудь приложения
browserify('client.js').bundle(function (err, src) {
  if (err) throw err;

  // Конец DevTools профилирования...
  console.profileEnd('build');
});

Теперь мы запустим devtool с нашим файлом:

$ devtool app.js

После выполнения мы можем увидеть результат на вкладке Profiles.

Результат профилирования devtool с помощью Chrome DevTools

Мы можем использовать ссылки на правой панели для просмотра и отладки горячих путей кода:

Горячие пути кода в devtool

Дополнительные параметры

Эксперименты

Chrome постоянно добавляет новые возможности и эксперименты в своём DevTools, такие как инспектор обещаний. Вы можете включить его, нажав три точки в правом верхнем углу и выбрав Settings → Experiments.

Экспериментальные возможности Chrome DevTools

После включения нажмите клавишу Escape, чтобы вызвать инспектор обещаний.

Инспектор обещаний в Chrome DevTools

Подсказка

После нажатия Shift 6 раз на странице экспериментов вам откроется больше экспериментальных возможностей, включая и нестабильные.

Флаг --console

Вы можете перенаправить вывод в консоль обратно в терминал (process.stdout и process.stderr), что позволяет приукрасить вывод.

$ devtool test.js --console | tap-spec

Флаги -- и process.argv

Выши скрипты могут парсить process.argv также, как и в обычном Node.js приложении. Если вы передадите что-нибудь после команды полной остановки (--) в devtool, то оно будет доступно как новый элемент массива process.argv. Например:

$ devtool script.js --console -- input.txt

Теперь, ваш скрипт может выглядеть так:

var file = process.argv[2];
console.log('Файл: %s', file);

Вывод:

Файл: input.txt

Флаг --quit и --headless

Флаг --quit завершает процесс с кодом выхода 1, когда будет достигнута ошибка (например, ошибка синтаксиса или неперехваченного исключения).

Флаг --headless позволяет не открывать DevTools при запуске. Это может быть использовано для скриптов командной строки:

$ devtool render.js --quit --headless > result.png

Флаг --browser-field

Некоторые модули могут предоставлять точку входа, которую лучше запустить в браузере. Вы можете использовать флаг --browser-field для поддержки флагов package.json, когда это требуется модулям.

Например, мы можем использовать xhr-request, который использует технологию XHR, требующую поле "browser".

const request = require('xhr-request');

request('https://api.github.com/users/mattdesl/repos', {
  json: true
}, (err, data) => {
  if (err) throw err;
  console.log(data);
});

В терминале:

$ npm install xhr-request --save
$ devtool app.js --browser-field

Теперь мы можем инспектировать запросы на вкладке Network:

Вкладка Network Chrome DevTools в devtool

Флаг --no-node-timers

По умолчанию мы предоставляем глобальные setTimeout и setInterval, которые ведут себя также, как в Node.js, возвращая объект с функциями unred() и ref()).

Однако, вы можете отключить их, чтобы улучшить поддержку асинхронной трассировки стека.

$ devtool app.js --no-node-timers

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

Флаги V8

Вы можете добавить файл .devtoolrc в текущий каталог, содержащий дополнительные параметры, такие как флаги V8.

{
  "v8": {
    "flags": [
      "--harmony-destructuring"
    ]
  }
}

Смотрите здесь для получения дополнительной информации.

Подводные камни

Так как ваше приложение запускается в окружении браузера (Electron) и не является истинным окружением Node.js, то могут встречаться подводные камни, о которых вы должны быть в курсе.

Сравнение

Уже существуют некоторые отладчики для Node.js, поэтому вам могут быть интересны различия среди них.

WebStorm Debugger

Редактор WebStorm включает в себя весьма хороший отладчик Node.js. Это замечательно, если вы уже используете WebStorm как ваш редактор кода.

Отладчик в редакторе WebStorm

Однако, в нем отсутствуют некоторые функции и лоск Chrome DevTools:

  • Роскошная и интерактивная консоль
  • Пауза на исключениях
  • Асинхронные трассировки стека
  • Инспектор обещаний
  • Профили

Поскольку он интегрируется с вашим рабочим пространством WebStrom, можно вносить изменения и редактировать ваши файлы во время отладки. Также стоит отметить, что он работает в реальном окружении Node/V8, в отличие от devtool, так что это более надежный отладчик для широкого круга Node.js приложений.

iron-node

Отладчик iron-node

Это похожий отладчик, основанный на Electron. Он включает в себя встроенную команду перекомпиляции нативных аддонов и сложный графический интерфейс, который показывает ваш package.json и README.md.

devtool предоставляет различные возможности Node.js (как require.main, setTimeout и process.exit) и переопределение внутренних механизмов карт исходного кода (source maps), а также имеет улучшенный обработчик ошибок, инъекцию контрольных точек и поле "browser".

node-inspector

Отладчик node-inspector

Вам также может понравиться node-inspector, предлагающий использовать удалённую отладку вместо запуска приложений в окружении Electron.

Это означает, что ваш код будет запущен в настоящем Node.js окружении, без какого-либо window или другого Browser/Electron API, которое может загрязнять области и вызывать проблемы с некоторыми модулями. Он имеет наиболее полную поддержку больших Node.js приложений (в том числе нативных аддонов) и предоставляет больше контроля над экземпляром DevTools (то есть можно использовать контрольные точки и инспектировать запросы).

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

В тоже время, devtool старается обеспечить разработчиков уже привычным для них инструментом (Chrome DevTools), а также продвигает другие функции, такие как Browser/Electron API.