-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
surprising (if not understandable) results for first-paint when document.visibilityState === 'hidden'
#40
Comments
We've had some discussion about this previously, though I wasn't able to dig it up quickly. I think #3 + an API which makes it easy to check if the page was ever backgrounded is the best solution. Relying on visibilitychanged is a bit annoying, especially if you have weird timing issues with FCP firing before your visibilitychanged listener is registered. I agree we should add a note to the spec and other resources. |
My extremely naive take on:
is that PerformanceEntry should have some sort of |
Yup, I think that makes a lot of sense! |
The current recommendation is to use PageVisibility and exclude entries that are created after the first time in which the document becomes hidden. But I do think it might be useful to add some tainting attribution to PerformanceEntry itself (that would probably go on the PerformanceTimeline specification, not this one). |
I think we should be explicit in the spec that a document would only mark paint timing if it had been fully active and visible throughout its lifetime. |
I think it's an interesting idea but requires discussion because I'm not sure it's the correct solution. We're also needing a solution for other types of performance entries. See w3c/performance-timeline#105 |
I think that thread is relevant to |
I agree a restored document should also have an indication, but similarly, that doesn't seem like a unique concern for paint timing. Navigation Timing, resource timing, and user timings can similarly be impacted. It would be good to address this holistically. |
As an update, we discussed this on the call and from the email thread there seems to be support to having a PageVisibility observer, so that's the current approach we'll take to fixing this issue. |
@npm1 yes, it can be worked around with page visibility, but the problem is that the current results are surprising. Having a property on a Timing called Consider the 2 different user experiences:
I'd argue that especially for telemetry tools, more info here, the better. |
The result may be surprising, but as mentioned above, that's not unique to Paint Timing, and having a boolean value on the entry will give you less information than an observer. The impact of briefly being in the background and never being in the foreground can obviously be different on different timings. Compressing that information into a boolean seems extremely lossy. |
taintedReason wouldn't be a boolean. It would be a description of why it was tainted. |
What would be potential values? How would you use it? |
See above ^. My thought here is that ergonomics outweigh the workarounds with pageVisibility. |
We're not tackling 'other' reasons at this time, so it would basically be a boolean signal (backgrounded or not). Given the tradeoff of ergonomics vs flexibility, we had a thread in the web perf mailing list. People supported the observer instead of the explicit signal in the entry. Here it is: |
I read the thread and it seemed like most thought both 1 and 2 would be useful. I'm curious to see what the code looks like for the solution to this problem using a hypothetical buffered PageVisibilityObserver. I'm a bit confused though with where to register the feedback. Should the issue be discussed here or on the mailing list? |
Hmm good question, I guess we did both for this particular issue. Do you disagree with the current proposal to use PageVisibilityObserver along with documentation in PaintTiming to explicitly point out this issue to users? The code would look something like this I guess: // Calculate first time the page was backgrounded.
// Observer would need to include an entry corresponding to the initial state.
let firstBackground = -1;
new PageVisibilityObserver(entries => {
entries.forEach(entry => {
if (entry.visibilityState === "hidden") {
// startTime would be the time in which state change occurred.
firstBackground = entry.startTime;
return;
}
}
}).observe(true /* buffered */);
// Paint Timing would simply use firstBackground.
performance.getEntriesByType('paint').forEach(entry => {
if (firstBackground !== -1 && entry.startTime < firstBackground)
continue;
// Report entry to analytics
}); |
Yeah, that code doesn't bad but I do think users are going to have a hard time discovering the solution, and I think the feedback in the thread about other taint reasons, like having console open, is interesting. But perhaps when and if y'all decide to address devtools tainting, than that's the time to reraise this issue. |
To echo my comments from the public-web-perf list, I think the underlying problem on the discoverability front is that page visibility isn't what we're interested in observing in this case, but rather interventions* taking place that are triggered by that page visibility—accordingly, a possible solution is to provide links between affected performance entries and ReportingObserver's entries. * Note: I would include delayed first paint due to backgrounding in an overall "intervention" bucket even though it's not currently an intervention in the way that chrome typically uses that term, but interventions like Background Tab Resource Load Throttling would also directly impact paint timings even if paint while in a backgrounded state was possible. |
Unless it's defined in an interoperable way I don't think we'd be able to add it. |
I wrote a summary of the current discussions: https://bit.ly/364z2PB |
Thanks so much @npm1 for your patient and thoughtful write up and for summarizing and championing the concerns well. |
Hey! Just wanted to give an update here. There was not agreement regarding surfacing the |
Thanks for considering and all the listening and advocacy you did on behalf of the concern I raised here. I'll close this issue now. Keep up the great work! |
Consider the following code:
If the document is hidden when this page is first loaded, e.g. it's a background tab that got loaded after restarting chrome,
first-paint
andfirst-contentful-paint
will only trigger once the tab goes into the foreground. Once the tab goes into the foreground, entry.startTime will be the moment the tab is foregrounded - navigationStart.While this makes sense because the browser is actually not painting until you foreground... this is a footgun:
I see 3 solutions:
Thoughts?
The text was updated successfully, but these errors were encountered: