Gatherer — это ключевой компонент архитектуры Lighthouse, отвечающий за сбор данных о странице во время аудита. Каждый Gatherer инкапсулирует конкретную задачу: получение метаданных, измерение производительности, анализ DOM, проверку доступности и многое другое. Разработка собственного Gatherer требует понимания жизненного цикла Lighthouse и особенностей его взаимодействия с Chrome DevTools Protocol (CDP).
Каждый Gatherer реализуется как класс с методом
async gather(options). Метод gather вызывается
движком Lighthouse и получает объект options, содержащий
необходимые данные для работы:
Пример минимальной структуры Gatherer:
class MyGatherer {
async gather(options) {
const {driver, page} = options;
const result = await driver.sendCommand('Runtime.evaluate', {
expression: 'document.title',
});
return result.result.value;
}
}
module.exports = MyGatherer;
Все Gatherer используют driver.sendCommand для отправки
команд в браузер. Это позволяет выполнять любые действия, поддерживаемые
CDP, например:
Важно учитывать, что команды CDP асинхронны, поэтому методы Gatherer
должны быть async и корректно обрабатывать промисы.
Gatherer должен возвращать результат в стандартизированном формате. Lighthouse использует ключевые свойства для дальнейшей обработки:
Пример расширенного Gatherer с обработкой ошибок:
class TitleGatherer {
async gather(options) {
const {driver} = options;
try {
const result = await driver.sendCommand('Runtime.evaluate', {
expression: 'document.title',
});
return {value: result.result.value};
} catch (err) {
return {value: null, debugString: `Ошибка: ${err.message}`};
}
}
}
module.exports = TitleGatherer;
Некоторые Gatherer требуют результатов других Gatherer для своей
работы. Это реализуется через dependencies. Например,
Gatherer для анализа скриптов может использовать Gatherer для сетевых
запросов:
class ScriptAnalyzerGatherer {
static get meta() {
return {
dependencies: ['NetworkRequestsGatherer'],
};
}
async gather(options) {
const networkRequests = options.dependencies.NetworkRequestsGatherer;
// обработка запросов
return {value: networkRequests.filter(r => r.resourceType === 'Script')};
}
}
Lighthouse гарантирует, что Gatherer, от которых зависит текущий, будут выполнены раньше.
Gatherer могут выполняться параллельно, если они не имеют зависимостей. Это позволяет ускорить аудиты. Для корректного проектирования:
Для разработки и тестирования Gatherer используется
LH.Gatherer.runner, а также мокирование объектов
driver и page. Основные аспекты:
{value, debugString}.Пример теста с моками:
const MyGatherer = require('./my-gatherer');
const mockDriver = {
sendCommand: jest.fn().mockResolvedValue({result: {value: 'Test Title'}})
};
test('gather returns title', async () => {
const gatherer = new MyGatherer();
const result = await gatherer.gather({driver: mockDriver});
expect(result.value).toBe('Test Title');
});
value, debugString.Gatherer является фундаментом архитектуры Lighthouse, обеспечивая точное и структурированное получение данных с веб-страницы. Корректная разработка Gatherer позволяет создавать гибкие и расширяемые аудиты, которые легко интегрируются в существующую систему.