GoogleChrome / web-vitals

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

When is the most reasonable time to obtain the web-vitals value #320

Closed huanghairong2312 closed 1 year ago

huanghairong2312 commented 1 year ago

At present, I delay 5 seconds to obtain web-vitals data after the page is loaded, but the user may exit the page after staying for less than 5 seconds. If the delay time is too small, the obtained web-vitals value is not accurate. I hope to find a reasonable time to obtain web-vitals data only once and complete my own ajax data reporting, which not only ensures the accuracy of the web-vitals data value, but also ensures that the waiting delay time is not too long. If you take performance.timeOrigin as the starting point, how long is the most reasonable delay to obtain web-vitals data?

import { getCLS, getFCP, getLCP, getTTFB } from 'web-vitals';

const rumData = {
    fcp: -1,
    lcp: -1,
    cls: -1,
    ttfb: -1
}

setTimeout(() => {
    getFCP((metric: any) => {
      rumData.fcp = metric.value;
    });
    getLCP((metric: any) => {
      rumData.lcp = metric.value;
    }, true);
    geCLS((metric: any) => {
      rumData.cls = metric.value;
    }, true);
    getTTFB((metric: any) => {
      rumData.ttfb = metric.value;
    });

    $.ajax.post(url,rumdata); // post my page rum data
}, 5000)
tunetheweb commented 1 year ago

The web-vitals library automatically will emit the appropriate metrics at the latest possible time.

Take LCP for example. It is "finalized" after an interaction so the web-vitals.js library will call the onLCP callback at this time (note getLCP has been renamed onLCP in latest version of this library):

https://github.com/GoogleChrome/web-vitals/blob/9f11c4c6578fb4c5ee6fa4e32b9d1d756475f135/src/onLCP.ts#L93-L98

Similarly when the page is backgrounded the onLCP callback is also emitted (since the tab can be closed without being foregrounded again):

https://github.com/GoogleChrome/web-vitals/blob/9f11c4c6578fb4c5ee6fa4e32b9d1d756475f135/src/onLCP.ts#L100

This is not perfect, and can lead to under- or over-reporting. For example:

So, in short, you don't need to set a timeout - the library will take care of this for you using best practices. In future we may even use newer, more reliable APIs like the pendingBeaconAPI to close out some of the gaps above.

The alternative, is you can use the reportAllChanges option to report every instance (e.g. all LCP candidates as they fire) and dedup this at your own backend but the heuristics that web-vitals.js uses without this is usually sufficient and accurate enough for most cases.

huanghairong2312 commented 1 year ago

Thank you for your guidance and suggestions. At present, we use the "reportAllChanges" option. Taking "lcp" as an example, reporting multiple times is not a good solution for us, which will increase the data volume and system pressure;

So my question is whether there is a certain best time to obtain all the values of web-vitras at one time (including fcp, lcp, cls, ttfb, fid). If so, how can I get this time.

Thanks !

philipwalton commented 1 year ago

So my question is whether there is a certain best time to obtain all the values of web-vitras at one time (including fcp, lcp, cls, ttfb, fid). If so, how can I get this time.

I'd suggest using the batch multiple reports together example in the README.

tunetheweb commented 1 year ago

That's a good option too to get ALL the changes, but also reduce the number of reports sent as much as possible.

However, personally I find NOT using the reportAllChanges and just reporting when web-vitals.js emits them is usually good enough and a lot simpler. Even if that does emit one beacon per metric (at different times) rather than one combined beacon. The web-vitals.js library has been coded to emit "final" metrics as much as possible (with some small amount of duplication where this is not possible).

Both ways though, can still result in multiple beacons (e.g. CLS sent on visibility hidden, then again if there's more CLS after the page is made visible again).

Ultimately the beacons resally needs to be sent after the page is completely finished with by the user, but currently there is no good way to guarantee that since a page can be backgrounded but then either foregrounded or not - without the chance to send that final beacon in the latter case! So you're either left with a few options - none of which are ideal:

Personally I think the last option is the worst option IMHO.

As I say I hope the pendingBeaconAPI is the answer to all this, which should allow beacons to be queued, but not sent until the page is finished with - but still guaranteed (to all intents and purposes) to be sent then.