sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.58k stars 1.92k forks source link

Scroll Position Flicker on Back/Forward Navigate #10634

Open samstorment opened 1 year ago

samstorment commented 1 year ago

Describe the bug

Navigating back to a SvelteKit app after visiting an external link can cause scroll flickering for future client side navigations. Below is a gif from my reproduction where I do the following:

  1. Navigate to a link external to the SvelteKit app
  2. Click the browser back button to go back to the SvelteKit app
  3. Navigate to an internal link, then scroll down on the page
  4. Click the browser back button to go back to the previous page (and see very brief red flicker)

red-flicker

On step 4 above, there is a flash of the red heading before navigating back to the previous page. I believe this happens because the the scroll position of the previous page is incorrectly applied to the current page directly before navigating backwards. Because the previous page's scroll position is at the very top, the current page is scrolled to the top, briefly showing the red heading, although I'm not sure why.

Notably, I haven't been able to reproduce this without first navigating to an external link, then navigating back to my SvelteKit app with the browser back button (or any other means of triggering a back navigation like a keyboard shortcut).

Additionally, I haven't been able to reproduce this running on a local development server with a command like pnpm dev. Instead I've only seen this behavior on a site deployed to a production environment like Vercel, or a local development server served from pnpm build and pnpm preview. To me, this strongly suggests that there is some problem related to the browser's bfcache. The bfcache is disabled when there is a web socket connection, and I believe the hot module reloading that pnpm dev provides uses a web socket.

I've been able to reproduce this much more reliably on Firefox than any other browser, but it does happen in Chrome occasionally.

Spamming the back and forward buttons in chrome is a more reliable way to visualize weird scroll behavior surrounding back/forward navigations in chrome (this might just be a different bug?). The scroll positions are inconsistent as I jump between the two pages in the gif below:

yoyo

The hn.svelte.dev site is another example of this flicker bug when navigating back. Here is a backwards navigation in extreme slow motion showing the flicker in chrome.

https://github.com/sveltejs/kit/assets/57368524/630ce4da-e0dc-4fd3-a7e2-2639423b31ea

Reproduction

Reproduction Link. This is just a skeleton SvelteKit repo created with the recommended docs command of pnpm create svelte@latest bf-scroll-flicker-repro. It has routes/+page.svelte and routes/other/+page.svelte with very minimal code and no other additions. To reproduce the flicker effect do the following:

  1. Run pnpm build then pnpm preview to run a local version of the site with the bfcache enabled. (I never experienced the bug using pnpm dev for reasons mentioned in the bug description.)
  2. Click on the "External Link" to go to a site external to the SvelteKit app
  3. Click the browser back button to go back to the SvelteKit app
  4. Click on the "Internal Link", then scroll down on this page
  5. Click the browser back button to go back to the previous page (and see very brief red flicker)

See the bug description for more context.

Logs

No response

System Info

System:
    OS: Windows 10 10.0.22621
    CPU: (16) x64 AMD Ryzen 7 5800X 8-Core Processor
    Memory: 22.30 GB / 31.91 GB
  Binaries:
    Node: 16.18.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 3.3.0 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.6.4 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.7.0 - ~\AppData\Local\pnpm\pnpm.EXE
  Browsers:
    Edge: Spartan (44.22621.2134.0), Chromium (116.0.1938.62)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0
    @sveltejs/kit: ^1.20.4 => 1.23.0
    svelte: ^4.0.5 => 4.2.0
    vite: ^4.4.2 => 4.4.9

Severity

serious, but I can work around it

Additional Information

Making external links open in a new tab with target="_blank" prevents this behavior from happening, but I'd prefer not do that since I first encountered this bug in the context of a PWA. Forcing links to open in a new tab causes a weird blank screen to be displayed for a bit before navigating to the new site in the PWA's in-app browser view.

samstorment commented 1 year ago

I noticed that returning a Promise from the new onNavigate lifecycle function that takes a bit to resolve does a good job at illustrating the scroll flicker (which I know is not advised generally but seems useful here) . I updated my reproduction to the latest SvelteKit version and added a +layout.svelte with a commented out onNavigate function.

samstorment commented 4 months ago

I've updated my reproduction with another route called alert with two essentially identical pages. I think these pages showcase what is essentially the same bug (bfcache weirdness after back navigating from an external link) in a way that might be easier to visualize. These routes are completely independent of the original reproduction, so nothing should be changed there.

samstorment commented 4 months ago

I improved my reproduction and published it on vercel for convenient access. Here's the link

eltigerchino commented 4 months ago

Side note: I wasn't able to reproduce this on iOS Safari. I may have done it wrong but I should try to reproduce it on desktop too.