Как имитировать плохую оценку первой задержки ввода (Web Core Vitals)?

Мне нужно создать веб-страницу, которая будет генерировать неверное значение первой задержки ввода (FID).

Если вы не в курсе, FID является частью Google Web Core Vitals.

Я хочу имитировать неверный FID, потому что я тестирую инструмент сканирования веб-сайтов, который должен помечать неверное значение FID. Поэтому я хочу имитировать неправильное значение на веб-странице, чтобы убедиться, что оно работает.

Чтобы было ясно - я НЕ пытаюсь исправить свою первую задержку ввода. Я хочу создать веб-страницу, которая специально дает плохое значение задержки первого ввода.

Но я не уверен, как это сделать.

У меня есть HTML-страница с <button id = "button">Click Me</button>. И в <head> я добавил этот скрипт:

<script type = "module">
// Get the First Input Delay (FID) Score 
import {onFID} from 'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module';

// Get the button element
const button = document.getElementById('button');

// Add a click event listener to the button
button.addEventListener('click', async () => {
  // Make a delay
  await new Promise((resolve) => setTimeout(resolve, 5000));
  // Print the FID score to the console
  onFID(console.info);
});
</script>

Импортированный метод onFID — это то, что Google использует из Web Vitals для сообщения значения FID.

Вы можете увидеть живую версию вышеуказанного скрипта здесь: http://seosins.com/extra-pages/first-input-delay/

Но когда я нажимаю кнопку, через 5000 миллисекунд он печатает только FID около 3 миллисекунд.

Задержка в 5000 миллисекунд не включена в значение FID.

Почему он не сообщает значение FID как 5003 миллисекунды?

Когда я пытаюсь имитировать неправильное значение FID, я делаю что-то не так.

Что бы это могло быть?

Обновлять:

Как было предложено в комментариях, я также попытался добавить задержку на сервере с помощью Cloudflare Worker. Этот работник задержал ответ сервера на 5000 миллисекунд. Но это не сработало, потому что значение FID не изменилось.

Также я не думаю, что это правильный подход, потому что FID измеряет время с момента, когда пользователь впервые взаимодействует с вашим сайтом (т. к этому взаимодействию. В то время как Cloudflare Worker только замедлял первоначальный ответ сервера. Поэтому с тех пор я удалил этот эксперимент со страницы.

Это делается на стороне сервера.

mr mcwolf 16.12.2022 16:04

@mrmcwolf что нужно сделать на стороне сервера? Я использую Google Cloud Bucket для размещения файлов и Cloudflare для доступа к домену. Могу ли я что-нибудь там сделать?

TinyTiger 17.12.2022 03:15

ну, вы должны использовать sleep (или аналогичную функцию) там, прежде чем возвращать ответ (страницу) клиенту. Я не знаю, можете ли вы реализовать это с помощью сервисов Google (а не нет).

mr mcwolf 17.12.2022 07:51

@mrmcwolf Я пробовал это с помощью Cloudflare Worker, но, к сожалению, это не работает. Более подробная информация об этом была добавлена ​​в обновленный вопрос.

TinyTiger 17.12.2022 09:49

@mrmcwolf, это скорость отклика веб-страницы, а не отклик сервера (см. Мой ответ). Очевидно, что последнее может повлиять на первое, поэтому на сервер можно добавить некоторый код, например. преднамеренно медленно отвечать на синхронный запрос GET страницы для внешнего JS-файла, но зачем это делать, если вы можете гораздо проще ввести его непосредственно на веб-страницу, как я предлагаю в своем ответе?

Inigo 21.12.2022 00:17

@Inigo, я понятия не имею, чего пытается достичь ОП. Задержка должна быть реализована на стороне сервера (по крайней мере, я так понимаю). Теперь есть два места, где можно вызвать sleep. Прежде чем что-либо будет отправлено клиенту (OP говорит, что это не работает для него) или после отправки каких-либо данных (принудительно, скажем, с flush, потому что обычно серверы буферизуют вывод). С чисто практической точки зрения такая задержка имела бы смысл, например, в сценарии входа в систему, в котором фиксировано постоянное время отклика независимо от того, была ли процедура входа успешной или нет.

mr mcwolf 21.12.2022 08:13

Вот два варианта задержки, которые можно использовать на сервере. Реализация идет phpсон 1 , сон 2

mr mcwolf 21.12.2022 08:50

@mrmcwolf Я не думаю, что вы внимательно читали исходный вопрос или даже мой комментарий. Либо так, либо у вас такое же непонимание FID, как и у ОП. Опять же, см. мой ответ. Если я ошибаюсь, почему бы вам не написать реальный ответ и не объяснить, как делать то, о чем спрашивают (это прямо здесь): «Мне нужно создать веб-страницу, которая будет генерировать неправильное значение задержки первого ввода (FID)».

Inigo 21.12.2022 08:55
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
8
189
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, вы неправильно понимаете, что такое FID

Со страницы web.dev о задержке первого ввода (FID):

Что такое ФИД?

FID измеряет время с момента, когда пользователь впервые взаимодействует со страницей (то есть, когда он щелкает ссылку, нажимает кнопку или использует настраиваемый элемент управления на основе JavaScript) до момента, когда браузер фактически может начать обработку. обработчики событий в ответ на это взаимодействие.

и

💡 Гочки

FID измеряет только «задержку» обработки событий. Он не измеряет ни само время обработки события, ни время, необходимое браузеру для обновления пользовательского интерфейса после запуска обработчиков событий.

также:

В общем, задержка ввода (также известная как задержка ввода) возникает из-за того, что основной поток браузера занят чем-то другим, поэтому он не может (пока) ответить пользователю. Одной из распространенных причин этого может быть то, что браузер занят синтаксическим анализом и выполнением большого файла JavaScript, загруженного вашим приложением.

Вот мое понимание: фактическое измерение FID встроено в Chrome. Библиотека web-vitals имитирует это с помощью API измерения браузера. Измерение не основано на том, когда вызывается onFID; onFID просто настраивает прослушиватель событий измерения с помощью этих API. Измеряется время между нажатием пользователем чего-либо (например, кнопки) и запуском обработчика события, а не время, необходимое этому обработчику для завершения (см. вторую цитату выше).

Во-первых, нам нужно что-то, что занимает (т.е. блокирует) JS Event Loop

setTimeout не делает этого. Он просто задерживает, когда что-то происходит. Тем временем цикл событий может выполнять другую работу, например. обрабатывать пользовательский ввод. Вместо этого вам нужен код, который делает именно то, что вы не должны делать: синхронно выполнять длительную блокировку ЦП, тем самым предотвращая обработку других событий, включая пользовательский ввод, в цикле обработки событий.

Вот функция, которая блокирует поток на заданное время:

function blockThread (millis) {
    let start = Date.now()
    let x = 928342343234
    while ((Date.now() - start) < millis) {
        x = Math.sqrt(x) + 1
        x = x * x
    }
}

а может просто:

function blockThread (millis) {
    let start = Date.now()
    while ((Date.now() - start) < millis) {
    }
}

Теперь вопрос: когда и где мы блокируем цикл обработки событий?

Прежде чем я пришел к пониманию выше, моей первой мыслью было просто изменить ваш подход: заблокировать цикл событий в прослушивателе событий кнопки click. Возьмите свой код, удалите async и вызовите blockThread вместо установки таймера. Эта работающая демонстрация делает это:

// this version of blockThread returns some info useful for logging
function blockThread (millis) {
    let start = Date.now()
    let i = 0
    let x = 928342343234
    while (true) {
        i++
        x = Math.sqrt(x) + 1
        x = x * x
        let elapsed = (Date.now() - start)
        if (elapsed > millis) {
            return {elapsed: elapsed, loopIterations: i}
        }
    }
}

const button = document.getElementById('button');

button.addEventListener('click', () => {
  const r = blockThread(5000)
  console.info(`${r.elapsed} millis elapsed after ${r.loopIterations} loop iterations`)
  console.info('calling onFID')
  window.onFID(console.info)
  console.info('done')
})
<!DOCTYPE html>
<html>

<script type = "module">
  import {onFID} from 'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module'
  window.onFID = onFID
</script>

<head>
  <title>Title of the document</title>
</head>

<body>
  <button id='button'>Block for 5000 millis then get the First Input Delay (FID) Score</button> 👈🏾 click me!
</body>

<p> 🚩 Notice how the UI (i.e. StackOverflow) will be unresponsive to your clicks for 5 seconds after you press the above button. If you click on some other button or link on this page, it will only respond after the 5 seconds have elapsed</p>

</html>

Я бы попробовал подтвердить вышеизложенное, но я ожидаю, что это НЕ повлияет на измерение FID, потому что:

  1. И ваша версия, и моя блокирует во время выполнения обработчика события, но НЕ задерживает его запуск.

    Измеряется время между нажатием пользователем чего-либо (например, кнопки) и запуском обработчика события.

    Я уверен, что нам нужно заблокировать цикл событий до того, как пользователь нажмет на ввод, и на достаточно долгое время, чтобы он оставался заблокированным во время и после этого щелчка. FID измеряет, как долго цикл событий остается заблокированным после щелчка.

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

    Библиотека web-vitals имитирует внутренние измерения Chrome. Он должен инициализироваться и подключаться к API измерения браузера в качестве обратного вызова, чтобы иметь возможность измерять что-либо. Вот что делает звонок onFID.

Итак, давайте попробуем несколько вариантов...

начать блокировать цикл событий во время загрузки страницы

Глядя на Основные инструкции по использованию для web-vitals, я пришел к следующему:

<!-- This will run synchronously during page load -->
<script>
  import {onFID} from 'web-vitals.js'

  // Setup measurement of FID and log it as soon as it is
  // measured, e.g. after the user clicks the button.
  onFID(console.info)

  // !!! insert the blockThread function declaration here !!!

  // Block the event loop long enough so that you can click
  // on the button before the event loop is unblocked. We are
  // simulating page resources continuing to load that delays
  // the time an input's event handler is ever called.
  blockThread(5000)
</script>

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

начать блокировку после загрузки страницы и до того, как сработает событие DOMContentLoaded    👈🏾 (я ставлю на это)

<script>
  import {onFID} from 'web-vitals.js'
  onFID(console.info)
</script>
<script defer>
  // !!! insert the blockThread function declaration here !!!
  blockThread(5000)
</script>

Если это все еще не работает, попробуйте следующее:

начать блокировку при запуске события DOMContentLoaded

<script>
  import {onFID} from 'web-vitals.js'
  onFID(console.info)

  // !!! insert the blockThread function declaration here !!!

  window.addEventListener('DOMContentLoaded', (event) => {
    blockThread(5000)
  });
</script>

🌶 Посмотрите этот отличный ответ на Как заставить JavaScript выполняться после загрузки страницы? для большего количества вариантов.


Дайте мне знать, если ни один из них не работает или какой из них работает. У меня сейчас нет времени проверять это на себе.

Все ваши последние три решения работают, но только если я перезагружаю и сразу начинаю щелкать страницу. Это не имеет ничего общего с кнопкой на странице. Вы можете щелкнуть в любом месте, чтобы заставить его работать. Необходимость щелкнуть что-то имеет смысл, поскольку репозиторий Web Vitals даже говорит: «FID не сообщается, если пользователь никогда не взаимодействует со страницей». Но можно ли как-то автоматизировать клик с помощью JavaScript? Я безуспешно пытался использовать что-то вроде document.getElementById('button').click();.

TinyTiger 22.12.2022 08:03

Я на 99% уверен, что это невозможно, потому что в браузере весь пользовательский Javascript выполняется в одном потоке. Ваш вызов click() будет выполняться после того, как blockThread завершится, или даже до его начала, в зависимости от того, где вы его поместили, но не во время. Таким образом, вы не можете смоделировать человеческую сторону браузера с помощью JS; Настоящий человек «работает сам по себе». То, что я решил выше, это ваш вопрос: «Я хочу создать веб-страницу, которая намеренно дает плохое значение задержки первого ввода. Но я не уверен, как это сделать». и "Но когда я нажимаю кнопку..."

Inigo 22.12.2022 22:58

Так что поверьте, я ответил на ваш вопрос как можно лучше, учитывая, как вы его задали. Если вы измените свой вопрос, добавив: «Мне нужно, чтобы это работало автоматически без участия человека, и мое решение должно быть полностью реализовано на HTML-странице с Javascript и должно использовать библиотеку web-vitals», тогда я обновлю свой ответ, указав, что это невозможно и объясните, почему (по крайней мере, невозможно, если вы не взломаете библиотеку web-vitals, но это всего лишь сырая идея, которая может не сработать).

Inigo 22.12.2022 23:41

Но, возможно, вы задали совершенно неправильный вопрос. См. XY задача . Может быть, ваш вопрос на самом деле звучит так: «Как мне протестировать мой инструмент для сканирования веб-сайтов?» Если да, то это совершенно новый вопрос Stack Overflow, и вам необходимо предоставить достаточную информацию о том, как работает ваш инструмент, каковы требования к тестированию и что вы уже пробовали. У меня есть некоторые мысли, но они основаны на догадках о том, что вы пытаетесь сделать. Я уже потратил много времени на это, поэтому я не могу тратить его на предположения и ответы. Я старался быть максимально полезным.

Inigo 22.12.2022 23:42

Другие вопросы по теме