Как освоить отладку JavaScript

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

Эффективная отладка JavaScript включает в себя нечто большее, чем просто исправление ошибок. Для обеспечения бесперебойной работы приложения и наилучшего взаимодействия с пользователем требуется понимание того, как работает ваш код.

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

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

Пример приложения

Мы будем работать над простым приложением, которое увеличивает количество вычислений и регистрирует их в консоли. Это приложение демонстрирует, как сокращенный код может усложнить отладку и как карты исходных текстов могут помочь упростить процесс.

Создайте js-файлы, указанные ниже, и добавьте фрагменты кода, как показано на рисунке:

1.... src/counterCache.js

export const countCache = { 
     previousCount: 0, 
     currentCount: 0, 
     totalCount: 0 
}
export function updateCache(currentCount, previousCount) { 
     countCache.currentCount = currentCount; 
     countCache.previousCount = previousCount; c
     ountCache.totalCount = countCache.totalCount + countCache.currentCount; 
}

2.src/counter.js:

import { updateCache } from './counterCache.js';
let count = 0; 
export function incrementCounter() 
     { count += 1; 
     const previousCount = count; 
     updateCache(count, previousCount); 
}

3.src/index.js:

import { incrementCounter } from './counter';
import { countCache } from './counterCache';
const button = document.createElement('button');
const previousElement = document.getElementById('previous');
const currentElement = document.getElementById('current');
const totalElement = document.getElementById('total');
button.innerText = 'Click me';
document.body.appendChild(button);
button.addEventListener('click', () => {
     incrementCounter();
     previousElement.innerText = countCache.previousCount;
     currentElement.innerText = countCache.currentCount;
     totalElement.innerText = countCache.total();
});

В свой файл package.json добавьте пакеты webpack, как показано ниже, затем запустите npm i для их установки. Мы будем использовать webpack как часть процесса сборки для создания сокращенного кода для производства:

  "devDependencies": {
    "webpack": "^5.96.1",
    "webpack-cli": "^5.1.4"
  }

Чтобы включить минимизацию кода, добавьте файл webpack.config.js со следующим фрагментом. Установка режима на рабочий указывает webpack на необходимость применения оптимизаций, таких как модификация:

 const path = require('path');
    module.exports = {
        mode: 'production', // Enables optimizations like minification and tree-shaking
        entry: './src/index.js', // Specifies the entry point of your application
        output: {
            path: path.resolve(__dirname, 'dist'),// Defines the output directory for bundled files
            filename: 'bundle.js',// Specifies the name of the bundled file
        },
    };

Теперь запустите npx webpack, чтобы объединить и минимизировать ваш код. dist/bundle.js Файл создается с содержимым, как показано ниже. При минимизации скрываются имена переменных и функций и удаляются ненужные символы, такие как пробелы, комментарии и неиспользуемый код, что позволяет уменьшить размер выходного файла и ускорить его загрузку:

(()=>{"use strict";const t={};let e=0;const n=document.createElement("button"),o=document.getElementById("previous"),u=document.getElementById("current"),r=document.getElementById("total");n.innerText="Click me",document.body.appendChild(n),n.addEventListener("click",(()=>{var n,c;e+=1,n=e,c=e,t.currentCount=n,t.previousCount=c,t.totalCount=t.totalCount||0+t.currentCount,o.innerText=t.previousCount,u.innerText=t.currentCount,r.innerText=t.total()}))})();

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

<<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Debugging Example</title>
    <link rel="stylesheet" href="styles.css"> 
</head>
<body>
    <h1>Web Debug App</h1>
    <p>Check console for bug</p>
    <table>
        <thead>
            <tr>
                <th>Previous count</th>
                <th>Current count</th>
                <th>Total count</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td id="previous">0</td>
                <td id="current">0</td>
                <td id="total">0</td>
            </tr>
    </table>

    <script src="./dist/bundle.js" ></script> <!-- Include the bundled output -->
</body>
</html>

Наконец, запустите приложение и проверьте консоль после нажатия кнопки. Для локального просмотра приложения вы можете использовать расширение Live Server в VS Code:

app error using minified code

Bundled source file

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

8 Стратегий отладки JavaScript для веб-приложений

Давайте продемонстрируем восемь методов, которые помогут немного упростить отладку JavaScript:

1. Исходные карты

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

Чтобы сгенерировать исходные карты с помощью webpack, обновите файл webpack.config.js следующим образом:

Строка devtool: 'source-map' или devtool: 'eval-source-map' указывает webpack сгенерировать внешний файл .map, который сопоставляет уменьшенный код с вашим исходным кодом. URL-адрес исходного файла карты также добавляется к уменьшенному коду в файле bundle.js.

Теперь запустите npx webpack. Файл .map будет создан вместе с вашим уменьшенным пакетом. Запустите приложение с помощью локального сервера и откройте его в окне браузера в режиме инкогнито. Это предотвратит вмешательство расширений браузера и кэшированных файлов в процесс отладки.

При создании исходных карт делаются следующие наблюдения:

  1. Ошибка связана с файлом counter.js, который является исходным кодом
  2. Исходная карта, bundle.js.map, успешно извлечена и видна на вкладке Ресурсы разработчика
  3. На вкладке "Источники" инструменты разработчика отображают исходный код и проблемную строку

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

app error from source maps

mapped source code javascript debugging

С описанной выше явной ошибкой мы можем исправить ошибку и получить доступ к правильному свойству в countCache.

Наше руководство по использованию Chrome DevTools должно стать отличным началом работы. Чтобы открыть вкладку "Ресурсы разработчика", нажмите на значок "Еще", затем "Дополнительные инструменты" и "Ресурсы разработчика". На этой вкладке вы можете просмотреть статус загрузки исходных карт и даже загрузить исходные карты вручную:

accessing developer resources tab javascript debugging

Приведенный ниже фрагмент кода исправляет ошибку в консоли. Обновите свой код, затем запустите npx webpack для компиляции изменений. После завершения запустите приложение и просмотрите обновленные выходные данные в таблице:

totalElement.innerText = countCache.totalCount;

При нажатии на кнопку в настоящее время обновляется предыдущее значение count, текущее значение count и итоговое значение в таблице. Предполагается, что предыдущее значение count возвращает предыдущее значение count, а общее значение count возвращает сумму всех значений count. На данный момент предыдущее количество отображает текущее количество, в то время как общее количество остается равным единице.

В следующем разделе мы рассмотрим дополнительные методы отладки JavaScript, такие как использование точек останова и пошаговое выполнение кода, чтобы выявить и устранить эту проблему:

web debugging example app output

2. Точки останова

Точки останова позволяют приостанавливать выполнение кода на определенных строках, что помогает проверять переменные, вычислять выражения и понимать последовательность выполнения кода. В зависимости от вашей цели вы можете использовать различные точки останова. Например:

  • Строка кода... Приостанавливает выполнение вашего кода точно на указанной строке
  • Условная строка кода Приостанавливает выполнение только при выполнении указанного условия
  • Logpoint не приостанавливает выполнение кода, а вместо этого отправляет пользовательское сообщение на консоль при выполнении этой строки кода

В нашем примере приложения мы применим точку останова к функции incrementCounter. На панели "Источники" откройте файл counter.js и щелкните слева от шестой строки. Это устанавливает точку останова в строке кода после увеличения количества:

setting line of code breakpoint

Мы установим другую точку останова в пятой строке и отредактируем ее. Чтобы отредактировать нашу точку останова, мы щелкнем правой кнопкой мыши на выделенном разделе и затем выберем "Редактировать точку останова".:

edit breakpoint javascript debugging

Мы установим тип точки останова на Logpoint, затем введем сообщение, которое будет записано в консоль:

setting logpoint breakpoint

При нажатии на кнопку наше приложение приостанавливает работу в точке останова строки кода и выводит журнал отладки на консоль из заданной точки входа:

app paused line of code breakpoint

На изображении мы можем видеть следующие разделы:

  • Панель ”Точки останова" Помогает управлять вашими точками останова и переключать их. В настоящее время мы добавили две точки останова, в пятой и шестой строках. Эти точки останова можно включить или отключить с помощью панели
  • Панель ”Область действия" имеет решающее значение для проверки состояний и значений переменных в текущей точке останова
  • Элементы управления отладкой Это позволяет вам шаг за шагом перемещаться по вашему коду. Используются следующие элементы управления: возобновить, перейти, войти, выйти и step

Благодаря этому мы сможем продолжить отладку нашего приложения.

3. Панель управления

Панель scope может быть эффективна для отладки JavaScript, поскольку она позволяет просматривать переменные из исходного кода:

scope panel javascript debugging

Мы можем видеть следующие переменные области видимости:

  1. Локальные Это переменные, определенные в текущей выполняемой функции
  2. Закрытие Эти переменные извлекаются из областей внешнего блока выполняющейся функции или скрипта
  3. Закрытие Этот тип переменной получается из сгенерированных областей, например, с использованием файлов модуля
  4. Глобальные Это переменные, доступные во всем приложении

На панели scope и в точке останова log point мы можем видеть, что текущее значение равно единице, в то время как значение до увеличения равно нулю. Поэтому нам нужно сохранить значение до увеличения как предыдущее значение.

4. Пошаговое выполнение кода (step into, step over, step out)

Пошаговое выполнение вашего кода включает в себя навигацию по программе различными способами во время отладки JavaScript:

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

Вы можете использовать элементы управления отладкой для пошагового выполнения вашего кода. Элемент управления Step позволяет запускать ваш код по одной строке за раз. При нажатии на Step выполняется шестая строка и выполняется переход к седьмой строке. Обратите внимание, как изменяется значение previousCount в области видимости:

stepping through code

Пошаговое управление позволяет вам выполнять функцию, не проходя ее построчно:

stepping over code

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

step into and step out of a line of code

Â' 

Чтобы устранить проблему, мы обновим код, как показано ниже. Теперь в таблице корректно отображается предыдущее значение:

import { updateCache } from './counterCache.js';
let count = 0;
export function incrementCounter() {
    const previousCount = count;
    count += 1;
    updateCache(count, previousCount);
}

5. Стек вызовов

Стек вызовов показывает последовательность вызовов функций, которые привели к текущей точке кода.

Добавьте новую точку останова в файл counterCache.js как показано на рисунке, затем нажмите кнопку. Обратите внимание на панель стека вызовов:

call stack panel

Когда приложение выполняет шестую строку из counterCache.js. Чтобы наблюдать за выполнением любых функций в стеке, вы можете перезапустить их выполнение, используя Restart frame, как показано ниже.:

restart frame call stack

6. Игнорирование скриптов

При отладке вы можете захотеть игнорировать определенные скрипты в ходе рабочего процесса. Это помогает избежать сложностей кода из библиотек или генераторов кода. В нашем случае мы хотим игнорировать скрипт counter.js во время отладки.

На вкладке Страница щелкните правой кнопкой мыши на файле, который нужно игнорировать, и добавьте скрипт в список игнорируемых:

add script ignore list

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

ignored frames call stack

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

grouping source files

7. Следите за выражением лица

Отслеживание выражений позволяет отслеживать определенные переменные или выражения во время выполнения кода, что помогает отслеживать изменения в режиме реального времени. Вы можете добавить выражения, такие как countCache, для отслеживания значений по мере выполнения кода.:

adding watch expressions

8. Фрагменты кода для отладки

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

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

javascript debugging snippet

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

countCache.totalCount = (countCache.totalCount || 0) + currentCount;

Вы можете ознакомиться с дополнительными ресурсами по отладке веб-приложений, такими как эта статья об отладке приложений React с помощью React DevTools, в которой содержится ценная информация об отладке приложений на основе React. Кроме того, в этом руководстве по отладке Node.js с помощью Chrome DevTools приведены советы по отладке серверного JavaScript с использованием средств просмотра и других расширенных функций DevTools. Эти ресурсы могут дополнить описанные здесь методы и расширить ваши представления об отладке веб-приложений.

Вывод

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

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