Puppeteer – это официальный инструмент для тестирования Headless Chrome.
Он используется во многих приложениях, включая веб-сканирование, тестирование страниц и предварительный рендеринг. Одним из преимуществ использования Puppeteer является то, что с помощью Headless Chrome он позволяет отображать полные веб-страницы, Javascript и все такое. Это означает, что вы можете получить информацию, которая загружается на веб-страницы после первоначальной загрузки DOM.

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

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

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

Сегодня мы рассмотрим, как получить полное время веб-сайта с помощью Puppeteer.

Давайте начнем

Вам нужно будет установить несколько зависимостей, чтобы начать работу. А именно;

Node и Puppeteer

Итак, давайте сделаем это, идите к своему терминалу

Сначала давайте установим NPM (менеджер пакетов узла)

$ apt-get install npm

Теперь, когда мы это установили, давайте установим Puppeteer.

$ npm i puppeteer

Нам также нужно установить некоторые зависимости, чтобы Puppeteer был готов к работе, вот команда со списком пакетов

$ sudo apt-get install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

И с этим мы готовы к работе!

Создадим файл audit.js и отредактируем его

$ vi audit.js

В нашем файле аудита нам понадобится Puppeteer.

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

//We're requiring puppeteer for usage
const puppeteer = require("puppeteer");

//This will be our main function to get our timings
async function run() {
//We initialise a browser constant, it calls puppeteer, we add the --no-sandbox argument as we are logged into the root user account 
const browser = await puppeteer.launch({args: ['--no-sandbox']});
//With our browser we start a new page
const page = await browser.newPage();
//This gets the url argument we passed to the function (you'll see this during testing)
const url = process.argv[2];
//Now, we navigate to our url that we passed, we should set a timeout so that our program doesn't hang
//You'll notice we have "networkidle0", this is a command that we issue that instructs the browser that the page is finished loading once there has been 0 network connections for 500ms.
await page.goto(url, { waitUntil: "networkidle0", timeout: 10000 });
//We have the page, so let's get our html (we don't need this for this example, but its a good thing to know)
const html = await page.content();
//Here we pass our page to our function that will extract the timings, and we console.log the result to return it
console.log(await getTimings(page));
//Finally, we should close the browser
await browser.close();
}

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

Когда браузер загружает веб-страницу, он пытается собрать ее как можно быстрее. То есть за короткий промежуток времени, миллисекунды.

Поэтому, когда мы используем аргумент NetworkIdle0, мы, по сути, говорим

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

С этим покончено, давайте перейдем к нашей функции getTimings.

async function getTimings(page) {
//First things first, let's extract our timings from our window object
const performanceTiming = JSON.parse( 
  await page.evaluate(() => JSON.stringify(window.performance.timing))
);
//Now, we'll call our last function to map our timings and convert them to milli-seconds(ms), we pass our performanceTiming constant along with the timings we want to get from it.
return extractPerformanceTimings(
performanceTiming,
'responseEnd',
'domInteractive',
'domContentLoadedEventEnd',
'loadEventEnd'
);
}

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

//Our function accepts the timing and the names of the data elements we want to extract
const extractPerformanceTimings = (timing, ...dataNames) => {
//Firstly, We need our start time, the times supplied by our timing object are integer timestamps, so to get the duration of each event, we need to know when the event started
const navigationStart = timing.navigationStart;

//We initialise our object which we'll use to store our new info
const extractedData = {};
//We're cycling through our dataNames variable which contains the names of the timings we desire
dataNames.forEach(name => {
//Here, we're assigning the name of the dataName variable, to the difference between start time and the time our event ended.
extractedData[name] = timing[name] - navigationStart;
});
//Finally, we return the extracted data to the calling function
return extractedData;
};

Это весь код, который она написала!

Теперь давайте проведем небольшое тестирование. Давайте запустим команду ниже.

$ node /root/audit.js https://www.fleeksite.com/
//By the way, remember this? our url is at index 2, that's how we get the url below
const url = process.argv[2];

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

{ responseEnd: 242,
domInteractive: 908,
domContentLoadedEventEnd: 1037,
loadEventEnd: 1294 }

Это все!

Теперь у нас есть небольшой тестер, которому мы можем позвонить, чтобы отслеживать время загрузки (или даже если наш веб-сайт работает) и сообщать нам об этом. Доступно еще больше таймингов, которые вы можете предварительно просмотреть, зарегистрировав свой объект таймингов производительности на консоли.

Я надеюсь, что это было полезно для вас, спасибо за чтение! :)