Skip to content
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

Deferring (same-origin) navigation commit #10716

Open
noamr opened this issue Oct 22, 2024 · 3 comments
Open

Deferring (same-origin) navigation commit #10716

noamr opened this issue Oct 22, 2024 · 3 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: navigation

Comments

@noamr
Copy link
Contributor

noamr commented Oct 22, 2024

What problem are you trying to solve?

Sometimes when performing a (same-origin) navigation, the old page wants to perform some potentially async operations. This could be e.g. putting something into storage, or even completing an animation or some other UI flow in the context of the old page.

What solutions exist today?

To achieve that today, the old page has to intercept the navigation, e.g. with NavigateEvent.intercept or by capturing clicks, and then re-trigger the navigation once the operation is complete.

However, this is far from ideal, as the interception aborts the navigation fetch, creating a lag once the old page is ready to proceed. What's needed here is deferring rather than intercepting the navigation.

How would you solve it?

Proposing to add a capability to defer a PageSwapEvent, similar (or identical) to service worker's ExtendableEvent.

This would look like this:

async function exit_operation() {
...
}

onpageswap = event => {
  event.waitUntil(exit_operation());
};

Anything else?

Other alternatives considered:

  • Adding NavigateEvent.defer, similar to NavigateEvent.intercept: feels like something related to same-document navigation, while this is more about same-origin commits ("page swap").
  • Modifying intercept to have this new behavior with an option. Feels like this overloads something that has a clear purpose with additional purposes, creating unnecessary confusion.
@noamr noamr added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest labels Oct 22, 2024
@noamr noamr added the agenda+ To be discussed at a triage meeting label Nov 7, 2024
@annevk
Copy link
Member

annevk commented Nov 8, 2024

I'm a bit worried that this would make history traversal slow. The whole point of having a bfcache is so it's snappy to hit the back button. This would make the end user experience worse.

@noamr
Copy link
Contributor Author

noamr commented Nov 8, 2024

I'm a bit worried that this would make history traversal slow. The whole point of having a bfcache is so it's snappy to hit the back button. This would make the end user experience worse.

Not sure if we need to support this for history traversals. But yea it's one of these points where a smooth UI sometimes means a delay.

@nickcoury
Copy link

I've been running into this situation trying to design an ideally responsive user experience using cross-document View Transitions.

Because cross-doc VTs must wait for the next page to render, and in some cases it's ideal to use a render blocking attribute to wait for a shared element on the next page, it's possible and even common for a cross-doc VT to blow past RAIL guidelines. All of the approaches I've considered so far have significant tradeoffs, and this proposal would help minimize the tradeoffs.

Approach 1:
Use c-d VTs off the shelf. This can freeze the screen for up to several seconds, causing the navigation to feel unresponsive. Without render blocking (or with a short timeout), it loses the orienting and delightful benefits of VTs. With render blocking, it can potentially be several seconds or more on a slow connection to respond to user input.

Approach 2:
Play a short animation instantly to show the user their input was received. This can sometimes work, depending on the scenario. But if anyone has tried to use animations during navigation, they know there is no guarantee they will play, often jank out terribly, and can contend with the navigation itself. This also doesn't work for many use cases that I'd like to pursue, e.g. scrolling a carousel when an item is clicked to center it instantly and not when the next page arrives.

Approach 3:
Delay the navigation to finish the animation. This is the approach described in the original issue. This has the obvious downside of significantly delaying the navigation by the length of the animation to guarantee it plays. It also adds complexity and might have other technical side effects of trying to intercept the navigation then initiate it again from JS. There are also browsers that currently support c-d VTs but not the full navigation API (latest Safari, navigation API requires a feature flag).

Ideally, the solution would allow the following:

  1. User initiates the document navigation with a link click. The browser starts fetching the next page immediately.
  2. Using a JS hook, I can play a JS animation and wait for it to complete before the outgoing document is destroyed, ensuring a synchronously responsive user experience.
  3. The animation should be relatively short (<500ms) anyways, which should be shorter than the critical path server response in most or all cases.
  4. The old document is destroyed, new page is created, and the VT plays.

I understand the potential for accidentally misusing this feature, but it seems far better to offer this capability than making the default for c-d VTs require a network round trip in order to give visual feedback to user input which goes against RAIL, INP guidelines, and overall UX. I know one of the recommended solutions is prefetching + prerendering, but that's not always an option.

Some version of this, even with limitations, sounds like it can provide a viable solution.

@past past removed the agenda+ To be discussed at a triage meeting label Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: navigation
Development

No branches or pull requests

4 participants