GoogleChrome / web-vitals

Essential metrics for a healthy site.
https://web.dev/vitals
Apache License 2.0
7.59k stars 415 forks source link

Why is onCLS firing late #407

Closed adardesign closed 9 months ago

adardesign commented 11 months ago

when registering onCLS onINP onLCP then registering a visibilitychange what happens is that all metrics are available at this point but CLS is delayed

See:

  const script = document.createElement("script");
  script.src = "https://unpkg.com/web-vitals@3/dist/web-vitals.iife.js";
  script.onload = function () {
    const queue = new Set();
    function addToQueue(metric) {
      queue.add(metric);
    }

    window.flushQueue = () => {
      if (queue.size > 0) {
        // Note: JSON.stringify will likely include more data than you need.
        const queueData = Object.assign(...Array.from(queue, (v) => ({ [v.name]: v.value })));
        queueData.url = window.location.href.split("#")[0];
        queueData.referrer = document.referrer;
        queueData.deviceType = /Android|webOS|iPhone|iPad/i.test(navigator.userAgent) ? "mobile" : "desktop";
        queueData.browserName =  "// browserName()";
        queueData.connectionType = navigator.connection ? navigator.connection.effectiveType : "unknown";
        queueData.interactionCount = performance.interactionCount;

        const body = JSON.stringify(queueData);

        (navigator.sendBeacon && navigator.sendBeacon("/beacon/perf/navigation", body)) || fetch("/beacon/perf/navigation", { body, method: "POST", keepalive: true });
        totalCLS = 0; // reset CLS
        queue.clear();
      }
    };

    webVitals.onCLS(addToQueue);
    webVitals.onFID(addToQueue);
    webVitals.onLCP(addToQueue);
    webVitals.onTTFB(addToQueue);
    webVitals.onINP(addToQueue);

    addEventListener("visibilitychange", () => {
      if (document.visibilityState === "hidden") {
        flushQueue();
      }
    });
      };
  document.head.appendChild(script);
tunetheweb commented 10 months ago

Can you explain more what you mean? I tested above code and it's correctly registering CLS on visibility change.