When moving to a new route, transition current view out without delay

Eiskis
0
Eiskis
commented 7 months ago

What problem does this feature solve?

Currently the navigation behavior with Nuxt is the following:

  1. User clicks on a link
  2. Loading of new page starts
  3. User waits for new page load to complete
  4. Route updates
  5. Exit transition of current view plays
  6. Enter transition of new view plays
  7. Navigation is complete

This is not ideal UX-wise. Even when I make efforts to make my page quite fast and enable the loading indicator, the load times are inconsistent, and the page feels broken and frozen upon clicking a link as a result.

What does the proposed changes look like?

I think a better behavior would be the following:

  1. User clicks on a link
  2. Route updates
  3. Loading of new page starts
  4. Exit transition of current view plays
  5. User waits for new page load to complete
  6. Enter transition of new view plays
  7. Navigation is complete

This way, we mitigate the problems significantly by taking advantage of two common patterns: offering immediate feedback after user interaction, and using exit transition duration to hide part of the loading time.

I don't think there's need to take away the current behavior, but to rather a new alternative as an option, and also consider using it as a default. I'm sure I'm not the first one thinking of this but could still find no issues or discussion around it. Also whether the route visibly updating immediately or during the transition phase… probably not that big a deal, but immediate feedback is good.

I'm not really up-to-date on all the tech behind the navigation logic, but I think this could drastically improve the perceived performance of Nuxt sites, hiding most of the page loads behind transitions.

EDIT:

A couple more points to clarify:

  • I'm not proposing any changes to the loading bar - at least nothing comes to mind that would need it.
  • I could already move loading logic from asyncData to other lifecycle hooks, in which case I get detailed control over my loading and wait time behavior. But I of course rely on asyncData for a reason, which is I want my prerendered pages to have the content available.
  • I'm not proposing rendering the new page without asyncData completing first. I'm proposing removing current page without delay, and waiting for the new page to load after that, if loading still takes time.

Of course it would be awesome to have even more controls over how long loading times are handled between transitions, or even rendering (some) pages before asyncData completes in SPA mode only (i.e. allowing devs to write custom loading behavior while still staying server-render-friendly).

idea
0
Eiskis
0
Eiskis
commented 7 months ago

One point about the route updates.

Let's say I have a sidebar panel with a menu that I want to close as the user clicks on any link. I can attach a watcher to current route and close it upon update. It he route update is immediate, user will get immediate feedback as well. Right now I have to either explicitly attach the close behavior to every link in my menu, or force the user to wait the page to load while the menu is open, after which the menu will close.

So if the route updates are immediate, I can orchestrate things better so that transitions related to the desired route can start playing as soon as possible. This is kinda analogous to how web works anyway, meaning the DOM reflects the desired state and the browser will transition elements if they are not where they ought to be.

0
Timkor
6
Timkor
commented 7 months ago

@eiski
You could fetch the data in mounted:

        mounted() {
                fetch('...').then((data) => {
                    Object.assign(this, data);
                })
        }
0
Eiskis
0
Eiskis
commented 7 months ago

You could fetch the data in mounted:

This is of course true, but then my app becomes basically just a normal SPA and not an SEO-friendly universal/prerendered app - which is the reason I use this awesome, awesome project! I'll edit the original post to highlight this.

0
manniL
5.8k
manniL
commented 7 months ago
0
Eiskis
0
Eiskis
commented 7 months ago

Is this a duplicate of #2568 ?

I knew I wasn't the first one!

It's close but not really an exact duplicate. I'd be happy to see the changes proposed there, but I'm proposing a different solution here (to the same problem). I think both can coexist though.

My proposal was basically a new transition mode, meaning old page is transitioned out without delay but asyncData is still respected for the new page. This could just be a catch-all default behavior you could enable for your entire application in nuxt.conf.js with one parameter or maybe a function that resolves per route.

I do see the need for more fine-grained loading handling for specific views, but with my proposal you can still write pages as you do now, meaning you don't have to cover that additional isLoading state.

0
Timkor
6
Timkor
commented 7 months ago

You could also use a plugin for client side. Which fetches the data after route transition:

export default ({app}, inject) => {
    app.router.afterEach(() => {
        // Get the current page and call a load method
       // Commit it to the store, or apply it to the pagecomponent
    })
})

And use a middleware server side:

export default ({ app, req, res, route, store, redirect, isHMR }) => {
    if (process.server) {
        // Get the current page and call a load method
        // Commit it to the store, or apply it to the pagecomponent
        return fetchPromise; // This is important
    }
})
0
Eiskis
0
Eiskis
commented 7 months ago

You could also use a plugin for client side. Which fetches the data after route transition:

Yeah I can see how that could work. I could set up named page transitions and use a mixin for every page component that would introduce generic loading state behavior for a new page that is still waiting for page data to be there, and transition itself in once done.

I guess I would be able to reach the behavior like this, but this does require a lot of workarounds, careful architecture and very detailed knowledge of how Nuxt works and careful orchestration of design elements and custom transitions to make it work. I think I'll try messing around with this kind of approach to see if I can get it working, but I don't think it's a good solution for the general public.

0
benoitemile
95
benoitemile
commented 7 months ago

I would invert 5 and 6.
Transitioning to our new page would leave us handle some placeholder blocks (for example) until data is done loading.

0
Informations
Feature RequestOpen
#c8620 - Created 7 months ago