Streaming promises broken on Safari (due to Safari not rendering incomplete response)
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
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
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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