Lighthouse изначально разрабатывался как инструмент для последовательного аудита веб-страниц. Однако с ростом числа метрик и аудитов в проекте возникла необходимость ускорения анализа за счет параллельного выполнения. Параллелизация позволяет одновременно запускать несколько аудитов или их этапов, минимизируя общее время тестирования.
Ключевым элементом является контроллер потоков (Task Runner), который управляет очередью аудитов и выделением ресурсов. Каждый аудиторный модуль может выполняться как отдельная асинхронная задача, что особенно важно при работе с тяжелыми аудитами, такими как анализ производительности и рендеринга.
Каждый аудит в Lighthouse представлен как объект с методами
meta и audit. Метод audit может
возвращать Promise, что позволяет запускать несколько
аудитов одновременно без блокировки основного потока:
const auditPromises = audits.map(audit => audit.audit({artifacts}));
const results = await Promise.all(auditPromises);
Использование Promise.all позволяет ожидать завершения
всех аудитов одновременно, что сокращает время ожидания, особенно на
страницах с большим количеством ресурсов.
Не все аудиты могут выполняться независимо. Некоторые аудиты требуют предварительных данных, получаемых другими аудитами. Для решения этой задачи Lighthouse использует систему артефактов (artifacts). Артефакты собираются на раннем этапе и передаются в нужные аудиты:
artifacts.URL — данные о проверяемом URL.artifacts.DevToolsLog — журнал сетевых и
пользовательских событий.artifacts.Trace — трейс страницы для анализа
производительности.Это позволяет запускать независимые аудиты параллельно, а зависимые — синхронизированно, используя уже собранные артефакты.
Для оптимизации нагрузки на систему и предотвращения ошибок из-за чрезмерного параллелизма в Lighthouse предусмотрена ограниченная очередь задач. Параметры ограничителя можно настраивать:
const pLimit = require('p-limit');
const limit = pLimit(5); // максимум 5 задач одновременно
const limitedPromises = audits.map(audit => limit(() => audit.audit({artifacts})));
const results = await Promise.all(limitedPromises);
Такой подход предотвращает перегрузку процессора и сети, сохраняя стабильность работы инструментов анализа.
Некоторые аудиты требуют загрузки страницы в браузере через Puppeteer. Здесь параллельность достигается за счет нескольких экземпляров Chromium:
Пример создания нескольких экземпляров браузера:
const puppeteer = require('puppeteer');
const browsers = await Promise.all(
[1,2,3].map(() => puppeteer.launch())
);
// запуск аудитов на каждом браузере
const results = await Promise.all(browsers.map(browser => runAudit(browser)));
Lighthouse применяет адаптивное управление параллелизмом, учитывающее:
Такой подход позволяет минимизировать время аудита без риска падения процессов или потери точности данных.
Для контроля выполнения параллельных задач используется расширенное логирование:
Пример логирования:
console.time('audit-performance');
await audit.audit({artifacts});
console.timeEnd('audit-performance');
Эти данные позволяют выявлять узкие места и корректировать параметры параллельного запуска.
Использование этих подходов делает Lighthouse эффективным инструментом для анализа крупных и сложных веб-проектов, позволяя проводить аудит быстрее и с меньшей нагрузкой на систему.