WICG / soft-navigations

Heuristics to detect Single Page Apps soft navigations
https://wicg.github.io/soft-navigations/
Other
46 stars 6 forks source link

When should `duration` end? #4

Closed mmocny closed 10 months ago

mmocny commented 1 year ago

Currently, the duration of a soft-navigation is state to be:

duration would be the time from startTime until the point in which all the tasks spawned by the user click were finished.

However, that seems to imply that duration ends after FCP and LCP. Besides potentially being problematic in terms of when these values are exposed to the performance timeLine (I think the navigation needs to be exposed before the other entries) -- I also would have expected that the duration of the navigation would end at the time that the navigation is "committed" rather than "fully loaded".

As such, should it really be when "all tasks" spawned are finished, or just when the soft-nav criteria are met?

yoavweiss commented 1 year ago

Besides potentially being problematic in terms of when these values are exposed to the performance timeLine

That's a good point, as we don't want to delay the SoftNavigationEntry too much.

When would you consider a soft navigation "committed"?

mmocny commented 1 year ago

I assumed that as soon as we decide to slice the performance timeline, aka to assign a new navigationId, the soft-navigation entry should be reported before any other performance entry that may reference.

This would mark the start rather than the end of the navigation.

yoavweiss commented 1 year ago

Yeah. As the "duration" bit is very speculative (we're not currently doing anything with it in the implementation), I'll just scrap it. We can then mint a "soft navigation end" entry if/when it's relevant.

yoavweiss commented 1 year ago

Modified the text to point to this issue. With that, what would be a useful value?

Options:

mmocny commented 1 year ago

I do think "the time of the decision that this is a soft navigation" (perhaps it should be the end time of the task that did that?) is a useful time point. Specifically: Click -> fetch start -> fetch completion -> apply history change + dom update, it would seem interesting to know if it took a long time for those dom changes to be applied as distinct from how long it took fo FCP/LCP events fire after that point.

I think its reasonable to consider that the duration, but we may also want to expose the time point via a special attribute (similar to how loadTime/renderTime are named time points for element timing).

paulirish commented 1 year ago

After thinking about #14 I'm seeing this as the next area of ambiguity. (Both duration and when we open consideration for the FCP..)

This is the base case thats fairly unambiguous (I hope?)

image

But how about this? (There's a few diff things going on here)....

image

(excalidraw link)

When's the FCP?

I don't know modern convention, but I've seen folks take differing approaches on updating the url (at least with pushState).. You can set it early and optimistically, even before your fetch.. You could do this, but then pushState backwards if there was an error. Or you can pushState conservatively, only after all DOM changes... (and there could be more complicated patterns intermixing replaceState/pushState). Again, I don't know how most frameworks manage this these days, but... conceptually there's a lot of room for variation. We don't want to incentivize creating more history entries than necessary.

In a world where the FCP is F1, it's almost always going to be flagging a paint showing a a:active or button:focus state, which is far too early to suggest the navigation has started successfully.


My intuition is that the FCP is the paint belonging to the frame generated by the task (via task attribution) that has the ModifiedDOM or SawURLChange operation (whichever is last). And this'd have to handle the above no-paint case.

Bringing it back to duration. I like the above idea that it ends at the "softnav decision point". But in that case, this "fcp reset point" timestamp is notable, and different, and perhaps deserves a special attribute?

mmocny commented 1 year ago

Thanks for the excalidraw diagram.

My opinions here, I think align with your conclusion, except perhaps for the fcp reset point?:

Generally, I think this mildly incentivizes early application of URL, and certainly to do so before beginning to apply next-route DOM changes.

Yes, some frameworks don't apply the URL update until after fetch() finishes and after DOM updates are rendered() and ready to apply to the DOM-- but that change is still "in the same frame" as the next route UI.

I don't know any frameworks where UI updates start to trickle in under the previous route URL. (for example, if you were to hit refresh at that moment, you would load back to the previous route if you did that...).

Anyway, under those criteria, I think the problem will be in picking the right time points for FCP startTime (Issue #14), and SPA end time/duration-- but that seems a cosmetic metric.

Marking FCP endtime feels the most important, yet simplest to define -- if you allow for "URL must change first".

WDYT @yoavweiss

yoavweiss commented 1 year ago

Thanks @paulirish !! I think F2 is probably the best time to report in such a case, as it's the first paint that's a result of the DOM modification the user click triggered. That F2 paint may just be a spinner/etc, but that seems fine.

I need to examine how that can be supported in the implementation..

@mmocny - I don't think F2 would be the active style updates (I'd expect F1 to be that, and be the INP for that interaction). F2 would be the result of a DOM modification that descendent from the user click event handler.

mmocny commented 1 year ago

I agree that spinners are fine to count as FCP, but I still think URL modification should come before FCP is marked, and that FCP should come after Soft nav duration ends.

Otherwise, DOM modifications that are not related to the navigation would count-- and the same could be true for LCP.

Are there any example sites that apply a history change after the UI updates? I can find plenty that don't update URL right away (i.e. after network reply) but none that also start the transition eagerly.

Here's one example of a super responsive site that update the UI right away (loading indicator), then updates the URL after network response, then updates the UI to reflect the new route change: https://solid-movies.app/

I do think that the initial loading indicator is useful UX and makes the site feel more responsive. But if the site used an MPA navigation, or the new navigation API, to leverage the browser loading indicators, that would not have been marked as FCP -- yet would offer the same level of feedback.

I think the initial dom modification is a responsiveness win for the outgoing route, not a measure of loading performance for the incoming route.

(Having written all that up, I now realize that if the page updated the URL right away it would have counted as FCP... no perfect answers!)

yoavweiss commented 1 year ago

I agree that spinners are fine to count as FCP, but I still think URL modification should come before FCP is marked, and that FCP should come after Soft nav duration ends.

Otherwise, DOM modifications that are not related to the navigation would count-- and the same could be true for LCP.

That's not necessarily correct. We can track DOM modifications that are descendents of the user click event, and only count those as a softnav FCP if they came before the URL change.

Here's one example of a super responsive site that update the UI right away (loading indicator), then updates the URL after network response, then updates the UI to reflect the new route change: https://solid-movies.app/

I do think that the initial loading indicator is useful UX and makes the site feel more responsive. But if the site used an MPA navigation, or the new navigation API, to leverage the browser loading indicators, that would not have been marked as FCP -- yet would offer the same level of feedback.

I think the initial dom modification is a responsiveness win for the outgoing route, not a measure of loading performance for the incoming route.

For hard navigations that have a loading spinner, those count as FCP..

But I agree that it's a tricky question.

paulirish commented 1 year ago

(Thanks ya'll. This is good stuff.)

I like Michal's assertion that it'd be incredibly weird to do all DOM updates for the softnav and ship that frame, and then change the URL in the next frame. I support treating that as a not-well-supported scenario.

Given that, we can drop the conditional paint case from above. So here's a straightforward, typical-ish case:

image

wdyt?

yoavweiss commented 10 months ago

(apologies for the delay. Dropped the ball on getting back to this)

I think we all agree that duration should be at the "softnav declared" point in your diagram. Regarding FCP, it used to be implemented as F3. Nowadays, the implementation started internally accumulating potential FP/FCP/LCP entries so that it's now reporting F2.

I think that's better, at least in cases where the URL change happens after that first paint (or races with that first paint).

yoavweiss commented 10 months ago

Given we have a decision on duration (which is the title of this issue), let's continue paint discussions in https://github.com/WICG/soft-navigations/issues/29

I'll send a PR regarding duration and then close this one with it.