如何模拟糟糕的首次输入延迟(Web Core Vitals)分数?

Tin*_*ger 2 javascript seo page-load-time web-vitals core-web-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.log);
});
</script>
Run Code Online (Sandbox Code Playgroud)

导入的onFID方法是 Google 从 Web Vitals 中使用的方法来报告 FID 值。

您可以在此处查看上述脚本的实时版本:http ://seosins.com/extra-pages/first-input-delay/

但是当我单击按钮时,5000 毫秒后它只打印大约 3 毫秒的 FID。

5000 毫秒延迟不包含在 FID 值中。

为什么它不报告 FID 值 5003 毫秒?

当我尝试模拟错误的 FID 值时,我做错了事情。

会是什么呢?

更新:

正如评论中所建议的,我还尝试使用 Cloudflare Worker 在服务器上添加延迟。该工作人员将服务器响应延迟了 5000 毫秒。但它不起作用,因为FID值没有改变。

另外,我认为这不是正确的方法,因为 FID 测量的是从用户首次与您的网站交互(即单击链接、点击按钮等时)到浏览器实际能够响应的时间。到那个互动。而 Cloudflare Worker 只是减慢了初始服务器响应速度。因此我已经从页面上删除了这个实验。

vas*_*vas 5

我认为你误解了FID是什么

\n

来自web.dev 关于首次输入延迟 (FID) 的页面

\n
\n

什么是 FID?

\n

FID 测量从用户首次与页面交互(即,当他们单击链接、点击按钮或使用自定义的 JavaScript 驱动的控件时)到浏览器实际能够开始处理的时间响应该交互的事件处理程序。

\n
\n

\n
\n

陷阱

\n

FID仅测量事件处理中的“延迟”。它不测量事件处理时间本身,也不测量浏览器在运行事件处理程序后更新 UI 所需的时间。

\n
\n

还:

\n
\n

一般来说,发生输入延迟(又名输入延迟)是因为浏览器的主线程正忙于做其他事情,因此它(尚)无法响应用户。发生这种情况的一个常见原因是浏览器正忙于解析和执行应用程序加载的大型 JavaScript 文件。

\n
\n

我的理解是:实际的 FID 测量内置于 Chrome 中。该web-vitals库使用浏览器测量 API来模拟这一点。测量不是基于调用时间;而是基于调用时间。 只需使用这些 API 设置测量事件监听器即可。测量的是用户单击某物(例如按钮)和触发其事件处理程序之间的时间,而不是该处理程序完成所需的时间(请参见上面的第二个引用)。onFIDonFID

\n

首先,我们需要一些东西来占用(即阻塞)JS事件循环

\n

setTimeout不这样做。只是当事情发生时它会延迟。与此同时,事件循环可以自由地执行其他工作,例如处理用户输入。相反,您需要的代码完全执行您不应该执行的操作:同步执行一些冗长的阻塞 CPU 密集型工作,从而防止事件循环处理包括用户输入在内的其他事件。

\n

这是一个将阻塞线程一段给定时间的函数:

\n
function blockThread (millis) {\n    let start = Date.now()\n    let x = 928342343234\n    while ((Date.now() - start) < millis) {\n        x = Math.sqrt(x) + 1\n        x = x * x\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或者也许只是:

\n
function blockThread (millis) {\n    let start = Date.now()\n    while ((Date.now() - start) < millis) {\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在的问题是:我们何时/何处阻止事件循环?

\n

在我达到上述理解之前,我的第一个想法是修改你的方法:在按钮click事件侦听器中阻止事件循环。获取您的代码,删除async,然后调用blockThread而不是设置计时器。这个可运行的演示可以做到这一点:

\n

\r\n
\r\n
// this version of blockThread returns some info useful for logging\nfunction blockThread (millis) {\n    let start = Date.now()\n    let i = 0\n    let x = 928342343234\n    while (true) {\n        i++\n        x = Math.sqrt(x) + 1\n        x = x * x\n        let elapsed = (Date.now() - start)\n        if (elapsed > millis) {\n            return {elapsed: elapsed, loopIterations: i}\n        }\n    }\n}\n\nconst button = document.getElementById(\'button\');\n\nbutton.addEventListener(\'click\', () => {\n  const r = blockThread(5000)\n  console.log(`${r.elapsed} millis elapsed after ${r.loopIterations} loop iterations`)\n  console.log(\'calling onFID\')\n  window.onFID(console.log)\n  console.log(\'done\')\n})
Run Code Online (Sandbox Code Playgroud)\r\n
<!DOCTYPE html>\n<html>\n\n<script type="module">\n  import {onFID} from \'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module\'\n  window.onFID = onFID\n</script>\n\n<head>\n  <title>Title of the document</title>\n</head>\n\n<body>\n  <button id=\'button\'>Block for 5000 millis then get the First Input Delay (FID) Score</button>  click me!\n</body>\n\n<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>\n\n</html>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

我会尝试确认上述内容,但我希望它不会影响 FID 测量,因为:

\n
    \n
  1. 你的版本和我的版本都会在事件处理程序执行期间阻塞,但不会延迟其启动。

    \n
    \n

    测量的是用户单击某物(例如按钮)和触发其事件处理程序之间的时间。

    \n
    \n

    我确信我们需要在用户单击输入之前阻止事件循环,并持续足够长的时间,以使其在单击期间和之后保持阻塞状态。FID 测量的是点击后事件循环保持阻塞的时间。

    \n
  2. \n
  3. 我也很确定在阻止事件循环onFID 之前我们需要导入和调用。

    \n

    web-vitals模拟Chrome 的内部测量。它需要初始化并将自身作为回调附加到浏览器的测量 API,以便能够测量任何内容。这就是调用的作用onFID

    \n
  4. \n
\n

那么让我们尝试一些选择......

\n

页面加载时开始阻塞事件循环

\n

查看基本用法说明,我得到了以下结论:

\n
<!-- This will run synchronously during page load -->\n<script>\n  import {onFID} from \'web-vitals.js\'\n\n  // Setup measurement of FID and log it as soon as it is\n  // measured, e.g. after the user clicks the button.\n  onFID(console.log)\n\n  // !!! insert the blockThread function declaration here !!!\n\n  // Block the event loop long enough so that you can click\n  // on the button before the event loop is unblocked. We are\n  // simulating page resources continuing to load that delays\n  // the time an input\'s event handler is ever called.\n  blockThread(5000)\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

但我怀疑如上所述调用 blockThread 实际上也会阻止页面/DOM 加载,因此您甚至没有按钮可以单击,直到为时已晚。在这种情况下:

\n

在页面加载之后和之前开始阻塞DOMContentLoaded事件触发之前开始阻塞 \xc2\xa0\xc2\xa0 (我的赌注就是这个)

\n
<script>\n  import {onFID} from \'web-vitals.js\'\n  onFID(console.log)\n</script>\n<script defer>\n  // !!! insert the blockThread function declaration here !!!\n  blockThread(5000)\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

如果仍然不起作用,请尝试以下操作:

\n

开始阻塞时DOMContentLoaded当事件触发

\n
<script>\n  import {onFID} from \'web-vitals.js\'\n  onFID(console.log)\n\n  // !!! insert the blockThread function declaration here !!!\n\n  window.addEventListener(\'DOMContentLoaded\', (event) => {\n    blockThread(5000)\n  });\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n
\n

看看这个关于如何让 JavaScript 在页面加载后执行的优秀答案。更多变化。

\n
\n
\n

请告诉我这些方法是否不起作用,或者哪一个起作用。我现在没有时间亲自测试这一点。

\n