sveltejs / sveltejs/kit

Swipe to navigate back on iOS causes flicker of current page when `load` performs asynchronous work

Open
#10,700 10 comments 12 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

Setup: using adapter-node, you have two pages that both have a load function, regardless of if it's in a +page.(js/ts) or +page.server.(js/ts), and the load functions are not synchronous. You navigate from page A to page B, and then from page B, you swipe "back", to navigate back to page A. Initially, page A is shown, but it will flicker back to page B while the load function for page A is re-running.

Below is an image of what happens visually, using the iOS simulator to demonstrate.

https://github.com/sveltejs/kit/assets/5247826/9d65011e-aef0-4018-b580-21b513effa65

In this reproduction, I've set the timeout in the load function to be 1s in page A to make the flicker/lag in navigation more obvious.

In this second video, I've dropped the timeout in the load function to be 100ms. Here, you can see that if you are holding the back navigation for more time than it takes for the load function to complete, then there is no flicker back to page B. This is consistent with the behaviour that I've seen in production environments.

https://github.com/sveltejs/kit/assets/5247826/4be1cda1-26ee-44b4-89f7-722d9c062498

As a slightly separate, but likely related bug, I've also noticed cases where you swipe back to navigate back from page B to page A, and page A just never renders. However, the browser things the navigation has completed, so swiping back doesn't take you to page A, even though it looks like you're on page B - instead, it takes you to whatever page you were on prior to the initial visit to page A.

I haven't been able to reproduce this bug consistently, but ideally if the main issue is addressed, then this other bug may also be fixed in the process.

EDIT: I think this is related to #10512?

Reproduction

Reproduction:

  1. Clone repo, install deps, build app, then node build
  2. Open http://localhost:3000/ in an iOS simulator
  3. Click on the "sub route" <a /> tag on the main page
  4. Swipe back to navigate to the main page from the /sub route
  5. observe flicker

You can modify the setTimeout in the src/routes/+page.ts to make the flicker longer or shorter. In practice, I've noticed load functions (on heavier pages) taking 50-100ms to complete, so that would be a more accurate representation of what the flicker would look like in a production environment.

https://github.com/quentin-fox/back-navigation

Logs
No logs are generated by the server/browser when reproducing the issue.
System Info
System:
    OS: macOS 11.5.2
    CPU: (8) arm64 Apple M1
    Memory: 104.95 MB / 8.00 GB
    Shell: 3.6.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 20.5.1 - ~/.asdf/installs/nodejs/20.5.1/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.8.0 - ~/.asdf/plugins/nodejs/shims/npm
    Watchman: 2023.08.14.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 116.0.5845.179
    Chrome Canary: 119.0.5999.0
    Safari: 14.1.2
  npmPackages:
    @sveltejs/adapter-node: ^1.3.1 => 1.3.1 
    @sveltejs/adapter-static: ^2.0.3 => 2.0.3 
    @sveltejs/kit: ^1.20.4 => 1.24.1 
    svelte: ^4.0.5 => 4.2.0 
    vite: ^4.4.2 => 4.4.9
Severity

annoyance

Additional Information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Use the linked back-navigation reproduction and start with src/routes/+page.ts, where the delayed load is configured. Reproduce the swipe-back flow in an iOS simulator with different timeout values, then trace the navigation behavior during the asynchronous load. Done means returning from /sub to the main page does not flicker back to /sub and the page renders reliably.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.