sveltejs / sveltejs/kit

Streaming promises broken on Safari (due to Safari not rendering incomplete response)

Open
#10,315 14 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

blocked by upstream load / layout
Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

Streaming promises, i.e., returning a nested promise in a server-side data loader, doesn't work properly in Safari.

I believe the way SvelteKit attempts to accomplish this is by first sending the initial HTML document, keeping the connection alive, and then finally ending the response with another script tag that patches the previously sent HTML.

However, this would rely on the browser starting to render the document before the response is fully received, which is not something that should be taken for granted — Safari, for example, does not do this, and waits for the response to be fully received before rendering the page. That means, if the promise takes 10 seconds to resolve, the page will not begin to load (and not show the loading state as intended) for the entire 10 seconds, before finally loading with the data fully rendered.

Comparison between the two browsers:

https://github.com/sveltejs/kit/assets/20295134/55365b01-0c61-4c59-a165-1c9e54f8f95c

Reproduction

Repository: https://github.com/Rich-Harris/sveltekit-on-the-edge

Relevant line
Relevant lines

Reproduction steps:

  • Visit https://sveltekit-on-the-edge.vercel.app/edge/streaming
  • On Safari, the webpage loads for one second, rendering nothing, then finally loads with City and IP directly
  • On Chrome, the webpage loads immediately with the loading state, then one second later, shows City and IP
Logs

No response

System Info
System:
  OS: macOS 13.0
  CPU: (8) arm64 Apple M2
  Memory: 47.52 MB / 16.00 GB
  Shell: 5.8.1 - /bin/zsh
Binaries:
  Node: 18.15.0 - /run/current-system/sw/bin/node
  npm: 9.5.0 - /run/current-system/sw/bin/npm
  pnpm: 8.3.1 - /run/current-system/sw/bin/pnpm
Browsers:
  Chrome: 114.0.5735.198
  Safari: 16.1
npmPackages:
  @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
  @sveltejs/kit: ^1.20.4 => 1.21.0 
  svelte: ^4.0.0 => 4.0.1 
  vite: ^4.3.6 => 4.3.9 
Severity

serious, but I can work around it

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

Start with the linked reproduction at sveltekit-on-the-edge, especially src/routes/edge/streaming/+page.server.js line 15 and src/routes/edge/streaming/+page.svelte lines 12-18. Reproduce the streaming route in Safari and Chrome, then trace the SvelteKit streaming-promise handling involved. Done means Safari renders the loading state before the delayed City and IP values arrive, while the existing Chrome behavior remains correct.

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
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.