Моніторинг невикористаного CSS за допомогою грубої сили DevTools Protocol

20

Від автора: Chrome DevTools – обов’язковий інструмент аналізу для розуміння того, що відбувається під капотом програми, а також для проведення аудиту продуктивності. При взаємодії з сайтом, як звичайний користувач, за допомогою DevTools ви можете дізнатися найдрібніші деталі про сторінку. Інструмент відмінно підходить для ручного аналізу.

Однак якщо вам необхідний моніторинг CSS і аналіз веб-продуктивності щодо часу, цей інструмент може здатися слабким. Автоматизовані сервіси по синтетичному моніторингу не надають стільки інформації, скільки є в DevTools, і здебільшого вони імітують лише один тип взаємодії з користувачем – очікування завантаження сторінки.

У цьому пості я покажу, як за допомогою DevTools Protocol, Puppeteer і Headless Chrome створити інструмент моніторингу по потужності порівнянний з DevTools. З допомогою цього підходу ви зможете автоматизувати будь-яка дія, що виконується вручну в DevTools UI. Ми продемонструємо цю техніку на прикладі програмного відстеження процентного співвідношення невикористаного CSS в додатку.

Завдання: визначити реальне співвідношення невикористаного CSS

Наша мета – створити скрипт, який буде вимірювати відсоток незайнятого CSS цієї сторінки. Зверніть увагу, що користувач може взаємодіяти зі сторінкою і переміщатися за допомогою різних вкладок.

З допомогою DevTools можна виміряти обсяг невикористаного CSS на сторінці за допомогою вкладки Coverage. Відсоток незайнятого CSS після завантаження становить 55%, але після кліка на кожну вкладку застосовується більше CSS правил, і відсоток падає приблизно до 15%. Значно. Наша автоматизована завдання повинна відображати реальний відсоток незайнятого CSS, тобто наш скрипт повинен імітувати користувальницьке взаємодія і кліки по всім вкладкам.

Моніторинг невикористаного CSS за допомогою грубої сили DevTools Protocol

Крок 0: знайомтеся з Chrome без Chrome

Headless Chrome – нова функція, представлена в Chrome 59. Тепер ви можете запускати Chrome в режимі Headless Mode – тобто вікно не відкривається, а сайти рендеряться тільки в пам’яті. Нова можливість ідеально підходить для тестування і автоматизації.

Як і інші безголові браузери, його можна використовувати для автоматизації інтерфейсу взаємодії зі сторінкою. Так як це Chrome, Headless Mode можна використовувати для автоматизації дій DevTools. Ми будемо використовувати Headless Chrome автоматизації для завантаження та взаємодії зі сторінкою під час захоплення CSS. Headless Chrome можна контролювати через код з допомогою DevTools Protocol. Про нього ми і поговоримо далі.

Моніторинг невикористаного CSS за допомогою грубої сили DevTools Protocol

Крок 1: шпигує за DevTools через DevTools

DevTools UI схожий на інший інтерфейс Chrome, однак це одностраничное додаток, написаний на Web technologies. Це окремий проект, який можна завантажити і погратися. Так як це всього лише клієнтський додаток, воно повинне отримувати дані про инспектируемой сторінки через об’єкт Chrome. DevTools front end відкриває з’єднання WebSockets з Chrome і двома обмінами повідомленнями, відповідні DevTools Protocol.

Наприклад, відкрийте вкладку Console в DevTools і введіть 1+1 – це протокольні повідомлення, які будуть передані з і в DevTools Frontend:

Моніторинг невикористаного CSS за допомогою грубої сили DevTools Protocol

Саме тому ми можемо бути впевнені, що будь-яка дія, виконане вручну в DevTools, також можна запустити програмно через DevTools Protocol.

Щоб автоматизувати пошук невикористаного CSS, необхідно зрозуміти, які команди DevTools Protocol посилати під час старту/зупинки відстеження на вкладці DevTools Coverage. Ми знаємо, що DevTools UI – це веб-сторінка, яка використовує WebSockets для відправки протокольних команд, тому є один спосіб – використовувати DevTools, щоб шпигувати інспектувати DevTools. Як це зробити:

Запустіть Chrome з прапором —remote-debugging-port=9222.

Відкрийте будь-який сайт (приклад unused-css-example-site-qijunirqpu.now.sh).

Відкрийте нову вкладку і перейдіть на localhost:9222.

Виберіть сторінку з першої вкладки в списку Insectable pages. Має відкритися сторінка з DevTools UI, инспектирующим сторінку з першої вкладки. Будемо називати її DevTools #1.

Відкрийте DevTools, як зазвичай ви це робите! (cmd+opt+i або F12) На сторінці ви повинні побачити додатковий об’єкт DevTools, що інспектує DevTools UI з кроку 4. Назвемо його DevTools #2.

У DevTools #2 перейдіть на вкладку Network і виберіть фільтр WS.

Оновіть сторінку.

У DevTools #2 клікніть на один WebSocket і перейдіть на вкладку Frames.

У DevTools #1 виконайте дію, для якого необхідно знайти протокольну команду. У нашому випадку необхідно відкрити вкладку Coverage і стартувати/зупинити захоплення покриття.

Запишіть послані/отримані команди через WebSocket в DevTools #2. У нашому випадку метод для старту відстеження покриття CSS.startRuleUsageTracking, а для зупинки — CSS.stopRuleUsageTracking. Еврика!

Моніторинг невикористаного CSS за допомогою грубої сили DevTools Protocol

Крок 2: збираємо всі разом

Тепер ми знаємо, які команди DevTools Protocol використовувати. Тому тепер можна перейти до написання скрипта автоматизації. Скрипт будемо писати на Puppeteer – node.js бібліотеці для запуску та управління Headless Chrome. Це високорівнева абстракція поверх DevTools Protocol. Це досить зручно, тому що автоматизувати прості користувальницькі взаємодії з допомогою DevTools Protocol було б занадто утомливо. Наприклад, для імітації кліка користувача по кнопці через грубі команди DevTools Protocol, необхідно знайти координати елемента і викликати події mousePressed і mouseReleased. Puppeteer робить все інше, коли ви використовуєте її метод click.

Тим не менш, коли вам потрібно «забруднити руки» в грубих командах DevTools Protocol, Puppeteer дозволяє це зробити. Ось чому бібліотека ідеально підходить під нашу задачу. Ми будемо використовувати її зручну абстракцію для імітації кліка користувача по вкладках, а також можливість відправки чистих команд DevTools Protocol для старту/зупинки CSS відстеження.

Наш код:

const puppeteer = require(‘puppeteer’);
init();
async function init() {
//Open Headless Chrome
const browser = await puppeteer.launch();
//Open a new tab
const page = await browser.newPage();
//Start sending raw DevTools Protocol commands are sent using `client.send()`
//First off enable the necessary «Domains» for the DevTools commands we care about
const client = page._client;
await client.send(‘Page.enable’);
await client.send(‘DOM.enable’);
await client.send(‘CSS.enable’);
//Start tracking CSS coverage
await client.send(‘CSS.startRuleUsageTracking’);
//Add this event to be notified whenever a stylesheet is added
//(payload contains the stylesheet size which is needed to calculate the percentage)
const stylesheets = [];
client.on(‘CSS.styleSheetAdded’, stylesheet => {
stylesheets.push(stylesheet.header);
});
//Trigger the user interaction with the page to hit more CSS rules
//(in our case this means trigger clicking on each fo the tabs)
const url = ‘https://unused-css-example-site-qijunirqpu.now.sh’;
await page.goto(url);
await page.click(‘.tab.type2’);
await page.click(‘.tab.type3’);
await page.click(‘.tab.type4’);
//Stop tracking CSS and get `ruleUsage` data object
const { ruleUsage } = await client.send(‘CSS.stopRuleUsageTracking’);
//You can see how `calcUnusedCssPercentage` is implemented here:
//https://github.com/cowchimp/headless-devtools/blob/17398336400eae3a7088069f1a27639c2ad30ac2/src/calcUnusedCss/index.js#L25
//(not shown here for brevity and because it’s just in-memory math operations)
const unusedCSS = calcUnusedCssPercentage(stylesheets, ruleUsage);
console.log(`${unusedCSS}% of your CSS is unused`);
await browser.close();
}

Якщо хочете використовувати цей скрипт на своєму сайті, він доступний як NPM модуль, а повні вихідні коди лежать на github. Ця версія дозволяє передавати блок інструкцій з користувацькими взаємодіями у вигляді зовнішнього колбека.

Висновок

Ось і все, ми написали скрипт, який обчислює реальний відсоток незайнятого CSS в додатку. Вихлоп скрипта – «15% of your CSS is unused».

Не забувайте, що це лише один приклад спільних дій DevTools, корисних і які можна автоматизувати. Коли наступного разу будете робити щось через DevTools, запитайте себе, чи можна автоматизувати, і скільки часу це заощадить.