Как рассчитать загрузку страницы с помощью Pupppeteer? - PullRequest
1 голос
/ 01 мая 2019

Я пытаюсь получить время полной загрузки страницы в секундах с кукольником в Node, для этого я провожу некоторые исследования API и другие вопросы и создаю следующий код:

/* First Configuration */
    puppeteer.launch({
            defaultViewport: { width: 1600, height: 800 }
      }).then(async browser => {
        const page = await browser.newPage();
    await page.setCacheEnabled(false);
        await page.goto('https://stackoverflow.com', {waitUntil: 'networkidle0'});

        /* Get Page Metrics */

        const perf = await page.metrics();
        console.log(JSON.stringify(perf));

        /* Get Page Evaluate */

        const timing = await page.evaluate(() => {
            const result = {};
            for (const key of Object.keys(window.performance.timing.__proto__))
                result[key] = window.performance.timing[key];
            return result;
        });
        console.log(JSON.stringify(timing));

        /* Show Results on Browser Close */

        await browser.close().then(() => {

    var fullyLoadEvaluate = (timing.loadEventEnd - timing.navigationStart);
        console.log('Fully Load Time (Page Evaluate): ' + fullyLoadEvaluate);

        var fullyLoadMetrics = (perf.LayoutDuration + perf.RecalcStyleDuration + perf.ScriptDuration + perf.TaskDuration);
        console.log('Fully Load Time (Page Metrics): ' + fullyLoadMetrics);

        /* Send Response to Server */
        res.send('Check The Console');
        });

      });

В основном я использую два кода для возврата метрик, один из них page.metrics(), который возвращает следующие данные:

{"Timestamp":961736.600171,"Documents":8,"Frames":4,"JSEventListeners":375,"Nodes":8654,"LayoutCount":27,"RecalcStyleCount":31,"LayoutDuration":0.705517,"RecalcStyleDuration":0.144379,"ScriptDuration":0.527385,"TaskDuration":1.812213,"JSHeapUsedSize":11082496,"JSHeapTotalSize":20344832}

И последний page.evaluate(), вернуть следующее:

{"navigationStart":1556722407938,"unloadEventStart":0,"unloadEventEnd":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1556722407938,"domainLookupStart":1556722408247,"domainLookupEnd":1556722408548,"connectStart":1556722408548,"connectEnd":1556722408737,"secureConnectionStart":1556722408574,"requestStart":1556722408738,"responseStart":1556722408940,"responseEnd":1556722409087,"domLoading":1556722408957,"domInteractive":1556722409995,"domContentLoadedEventStart":1556722409995,"domContentLoadedEventEnd":1556722410190,"domComplete":1556722412584,"loadEventStart":1556722412584,"loadEventEnd":1556722412589,"toJSON":{}}

В моем примере я тестирую сайт https://stackoverflow.com. Как webpagetest.org и getmetrix.com , я пытаюсь получить Время полной загрузки страницы .

Я знаю, что такого рода значения противоречивы, но мне интересно, верны ли вычисляемые мной значения, и какой из двух результатов представляется более правильным? Fully Load Time (Page Evaluate) или Fully Load Time (Page Metrics)?

1 Ответ

2 голосов
/ 01 мая 2019

Вы можете использовать page.metrics() для сравнения двух точек во времени (например, до и после page.goto). Подход page.evaluate для чтения данных из performance API также является хорошей альтернативой. Как я уже указывал в комментарии, не определено, что следует считать «полной загрузкой страницы». Оба подхода действительны.

Это еще сложнее

Есть ряд вещей, которые люди могут считать загружаемой страницей:

  • DOMContentLoaded событие сработало
  • Load событие сработало
  • Время, которое требуется от начала навигации до тех пор, пока все ресурсы, встроенные в документ (например, загруженные изображения),
  • Время от начала навигации до загрузки всех ресурсов
  • Время до тех пор, пока не будет больше текущих сетевых запросов.
  • ...

Вы также должны решить, хотите ли вы, чтобы связанные с сетью фазы (например, DNS) были частью измерения. Вот пример запроса (сгенерированный с помощью вкладки Chrome DevTools Network), показывающий, насколько сложным может быть один запрос:

Chrome DevTools Network Timing

Существует также документ , объясняющий каждый из этих этапов.

Простой подход

Самый простой способ измерить время загрузки - это просто начать измерение при запуске навигации и прекратить измерение после загрузки страницы. Это можно сделать так:

const t1 = Date.now();
await page.goto('https://example.com');
const diff1 = Date.now() - t1;
console.log(`Time: ${diff1}ms`);

Обратите внимание, что есть и другие API (page.metrics, process.hrtime, perf_hooks) для получения более точных временных отметок.

Вы также можете передать опции в функцию page.goto, чтобы изменить разрешение обещания на что-то вроде этого (цитируется в документации):

Считать, что навигация завершена, если не более 0 сетевых подключений в течение не менее 500 мс

Для этого вам нужно будет использовать настройку networkidle0:

await page.goto('https://example.com', { waitUntil: 'networkidle0' });

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

Более сложный: используйте Performance API

Чтобы получить более точные результаты, вы можете использовать Performance API , как вы уже сделали в своем коде. Вместо прохождения прототипа window.performance вы также можете использовать функции performance.getEntries() или performance.toJSON(), например:

const perfData = await page.evaluate(() =>
    JSON.stringify(performance.toJSON(), null, 2)
);

Таким образом, вы получаете данные, которые выглядят так:

{
  "timeOrigin": 1556727036740.113,
  "timing": {
    "navigationStart": 1556727036740,
    "unloadEventStart": 0,
    "unloadEventEnd": 0,
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 1556727037227,
    "domainLookupStart": 1556727037230,
    "domainLookupEnd": 1556727037280,
    "connectStart": 1556727037280,
    "connectEnd": 1556727037348,
    "secureConnectionStart": 1556727037295,
    "requestStart": 1556727037349,
    "responseStart": 1556727037548,
    "responseEnd": 1556727037805,
    "domLoading": 1556727037566,
    "domInteractive": 1556727038555,
    "domContentLoadedEventStart": 1556727038555,
    "domContentLoadedEventEnd": 1556727038570,
    "domComplete": 1556727039073,
    "loadEventStart": 1556727039073,
    "loadEventEnd": 1556727039085
  },
  "navigation": {
    "type": 0,
    "redirectCount": 0
  }
}

Поэтому, если вы хотите узнать, сколько времени ушло с navigationStart до loadEventStart, вы вычтите одно значение из другого (например, 1556727039073 - 1556727036740 = 2333 мс).

Так какой же взять?

Это ваше решение. В целом, хорошей идеей является использование события Load в качестве отправной точки. Ожидание завершения всех запросов может фактически никогда не произойти, поскольку в фоновом режиме постоянно загружаются ресурсы. Использование networkidle2 в качестве waitUntil опция может быть альтернативой, если вы не хотите использовать событие загрузки.

В конце, однако, все зависит от вашего варианта использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...