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

Slow page changing #377

Open
DoctorRyner opened this issue Feb 14, 2024 · 25 comments
Open

Slow page changing #377

DoctorRyner opened this issue Feb 14, 2024 · 25 comments

Comments

@DoctorRyner
Copy link

Describe the bug

Changing pages takes way too much time on iOS and even on desktop if the app is a bit demanding like when it has a background animation. It doesn't matter is it's SSR or standard SPA. I checked with svelte-kit and it is always instant there

Your Example Website or App

any solid app with this router and links

Steps to Reproduce the Bug or Issue

  1. Click on a route, e.g. /about
  2. A delay <1 second appears
  3. Page changed

Expected behavior

  1. Click on a route, e.g. /about
  2. Page changed instantly

Screenshots or Videos

No response

Platform

  • OS: [iOS]
  • Browser: [Safari]
  • Version: [iOS 17.2.1]

Additional context

No response

@DoctorRyner
Copy link
Author

Here is the video of solid looking laggy even for the most basic view
https://github.com/solidjs/solid-router/assets/24430919/186fe747-700c-4696-81fd-78e482204545

@Brendonovich
Copy link
Contributor

A reproduction would really help here, even if it does happen with 'any solid app with this router and links', I for example haven't experienced it in my apps. Could it be something to do with transitions causing page navigation to be delayed while waiting for stuff to load?

@DoctorRyner
Copy link
Author

I'm not sure about transitions but it's slow. For reproduction do "npm create solid@latest" and select basic template, add any routes and use

@ryansolid
Copy link
Member

Yeah hmm.. I'm not seeing it. Even with 6x CPU slowdown on desktop. It is possible there is some sort of performance thing. Maybe even platform specific. Do you see this same lag on: https://docs.solidjs.com/? This is a real site so there are other considerations there but I just want to sort of figure out where to narrow this down a bit because as Brendonovich says there are 1000s of sites out there using the router and this hasn't been reported before.

@DoctorRyner
Copy link
Author

I experience it on iOS

RPReplay_Final1708106344.mp4
RPReplay_Final1708106237.mp4

@DoctorRyner
Copy link
Author

Look how slow it is on Solid compared to Svelte

@oddcelot
Copy link

Isn't this more related to network being slow and the routes being loaded lazily?
Maybe there is also a element in perception involved, since the nav on solid docs does close before the route is finished loading.

I noticed that the payload from the loaded route data in the svelte docs is like < 100B (depending on the page of course) while the route data loaded in solid docs is more in the ~ 80kB range.

@DoctorRyner did you have a look at the network tab (for size comparison) and while trying to throttle the network speed?

@DoctorRyner
Copy link
Author

The page size doesn’t matter, it’s slow even in bare app with no js/css

I use SvelteKit rn and I don’t have this issue in my app. Look at the video I posted above, this is how it works on an iPhone even on bare app. For some reason the route changing is slow on iPhone

@Manviel
Copy link

Manviel commented Feb 29, 2024

Yeah hmm.. I'm not seeing it. Even with 6x CPU slowdown on desktop. It is possible there is some sort of performance thing. Maybe even platform specific. Do you see this same lag on: https://docs.solidjs.com/? This is a real site so there are other considerations there but I just want to sort of figure out where to narrow this down a bit because as Brendonovich says there are 1000s of sites out there using the router and this hasn't been reported before.

Hello @oddcelot @ryansolid ,
Have you consider to change Network throttling to Slow 3g and try switching between routes. There is no indicator that the page is loading and it looks like the page is frozen.

@mattbdc
Copy link

mattbdc commented May 9, 2024

It isn't fetching from network after loading them first time.

It is slow even on a macbook m1 / asahi, compared to svelte docs. But I think it's related to expressive-code block being inited. As if you find parts that dont have many, and hide from active viewport, then it's fast, otherwise it's several hundred milliseconds, you can see the title change first and blink before the rest of the articles comes in (not from network), so whilst most people wouldn't consider that slow it's still odd. I think probably a docs issue

@DoctorRyner
Copy link
Author

@mattbdc nah, I first experienced it in my bare bone project, so it must be related to router

@Brendonovich
Copy link
Contributor

We've been experiencing this in a Tauri + Solid project on iOS, it seems to happen with <a> links but not <button onClick={() => navigate(...)}>

@jpdutoit
Copy link
Contributor

jpdutoit commented Jun 29, 2024

The problem is that safari iOS adds a 200ms delay to anchor links if you have a mouseover event installed. I tried finding an official source for this, but all I could find was a random reddit comment.

The following hack removes the delay for me.

function useFastAnchorLinks() {
  let skipNextMouseOver = false
  const onTouchStart = () => {
    skipNextMouseOver = true
  }
  const onCaptureMouseOver = (event: MouseEvent) => {
    if (skipNextMouseOver) {
      event.preventDefault()
      skipNextMouseOver = false
    }
  }
  document.addEventListener("touchstart", onTouchStart)
  document.addEventListener("mouseover", onCaptureMouseOver, { capture: true })

  onCleanup(() => {
    document.removeEventListener("touchstart", onTouchStart)
    document.removeEventListener("mouseover", onCaptureMouseOver, { capture: true })
  })
}

When I looked into this, I was surprised to see that solid-router hooks into a bunch of global events for this instead of attaching them to the A component alone.

Possible fixes:

  1. Don't install these handlers on mobile, but this might cause issues on tablets with a mouse connected?
  2. Use mouseenter instead of mouseover here
  3. Or maybe it is enough to call evt.preventDefault() inside the mouseover handler...

@jpdutoit
Copy link
Contributor

There is another source of a click delays that need separate fixing, though those are not caused by solid-router
You need something like the following in your head element.

<meta name="viewport" content="width=device-width, initial-scale=1" />

or alternatively, you need style="touch-action: manipulation;" on all your anchor links

@mattbdc
Copy link

mattbdc commented Jul 1, 2024

Interesting, just anecdotal/unbenchmarked it definitely felt like more than 200ms to me, it felt closer to 1s, I'm not sure I would notice 200ms, I wonder what svelte is doing as that didn't suffer..

@jpdutoit
Copy link
Contributor

jpdutoit commented Jul 1, 2024

Interesting, just anecdotal/unbenchmarked it definitely felt like more than 200ms to me, it felt closer to 1s, I'm not sure I would notice 200ms, I wonder what svelte is doing as that didn't suffer..

I think the delay mentioned in my second comment is more than 300ms. Perhaps they are even additive....

@JensForstmann
Copy link

JensForstmann commented Jul 7, 2024

I face the same problem with slow page changing when using either <A> or <a>.

A minimal reproduction code can be found here: https://github.com/JensForstmann/slow-solidjs-router

I also included a video/screen recording.

@Jylth
Copy link

Jylth commented Jul 14, 2024

Disabling route prefetching seems to fix this on IOS.

I personally disabled the default prefetching on hover behaviour and used an Intersection observer which tracks links appearing on the viewport and preloads the routes manually through the usePreloadRoute API. This setup requires detecting when new tags are loaded into the DOM to add them to the list of observed items.

Combined with a good CDN caching setup on preloaded queries, and this makes your app feel super fast and snappy on navigation.

@JensForstmann
Copy link

Disabling route prefetching seems to fix this on IOS.

Thanks for the tip. I've disabled it for my simple app and it makes it remarkably better to use on iOS.

@asilvadesigns
Copy link

Can someone share a code sample, I don’t see any option for disabling prefetch. I experience this delay on the docs as well.

@JensForstmann
Copy link

JensForstmann commented Sep 24, 2024

@asilvadesigns

<Router
  root={Root}
  preload={false} // <<<———-
>
   <Route path="/status" component={StatusPage} />
   <Route path="/history" component={HistoryPage} />
   <Route path="*" component={() => <Page404 />} />
</Router>

@ryansolid
Copy link
Member

ryansolid commented Sep 25, 2024

This is really unfortunate that iOS is delaying stuff when you have mouse events. Most frameworks these days have some sort of link prefetching by default. It is odd to me that something like Svelte docs wouldn't employ that technique. I wonder if we are supposed to use platform detection to decide and just disable on iOS or something. In fact I definitely see the Svelte website doing preloading in the docs on hover. So does it do the preloading on iOS I wonder.. does it do it with different events? Forcing the end developer to disable all preloading for all platforms feels terrible and I doubt anyone does that. I feel like we are missing a critical piece of information.

@jpdutoit your suggestions seem the most helpful but I have no way of confirming them.

  1. Good point about different pointer devices (which makes this less desirable)
  2. mouseenter/mouseleave don't bubble so they are not an option. We use delegation so that we don't need to hydrate that part of the page to get benefit.
  3. I have no way to confirm this does anything negative/positive

@oddcelot
Copy link

it might be just me, but i get at least perceived reduction in delay using a bit of CSS tested with repro from #377 (comment)

a {
  touch-action: none;
}

@jpdutoit
Copy link
Contributor

I was curious how Svelte does. From the docs:
On mobile, preloading begins on touchstart

For mouse they don't hook mouseover, they use a global mousemove instead:

Here is the relevant code from SvelteKit

@oddcelot
Copy link

oddcelot commented Sep 25, 2024

hmm, i was logging all the events on the element and onpointerover was the first in the list at least on safari/firefox
(on chrome it was onpointerrawupdate)
if there aren't any other implications it may be feasable to attatch the preload handling to the onpointerover event 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants