Skip to content

feat: out of order streaming for Suspense#8611

Draft
Varixo wants to merge 40 commits into
build/v2from
v2-out-of-order-streaming
Draft

feat: out of order streaming for Suspense#8611
Varixo wants to merge 40 commits into
build/v2from
v2-out-of-order-streaming

Conversation

@Varixo
Copy link
Copy Markdown
Member

@Varixo Varixo commented May 5, 2026

No description provided.

@Varixo Varixo self-assigned this May 5, 2026
@Varixo Varixo requested review from a team as code owners May 5, 2026 16:49
@Varixo Varixo added the V2 label May 5, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 5, 2026

🦋 Changeset detected

Latest commit: 91119b6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@qwik.dev/core Patch
eslint-plugin-qwik Patch
@qwik.dev/react Patch
@qwik.dev/router Patch
create-qwik Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@maiieul maiieul moved this from Backlog to Waiting For Review in Qwik Development May 5, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 5, 2026

Open in StackBlitz

@qwik.dev/core

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/core@8611

@qwik.dev/router

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/router@8611

eslint-plugin-qwik

npm i https://pkg.pr.new/QwikDev/qwik/eslint-plugin-qwik@8611

create-qwik

npm i https://pkg.pr.new/QwikDev/qwik/create-qwik@8611

@qwik.dev/optimizer

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/optimizer@8611

commit: 91119b6

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

built with Refined Cloudflare Pages Action

⚡ Cloudflare Pages Deployment

Name Status Preview Last Commit
qwik-docs ✅ Ready (View Log) Visit Preview 91119b6

@Varixo Varixo force-pushed the v2-out-of-order-streaming branch from e63fe47 to 915e9ba Compare May 7, 2026 14:06
@Varixo Varixo force-pushed the v2-out-of-order-streaming branch from 915e9ba to 303b6d1 Compare May 7, 2026 14:10
@Varixo Varixo force-pushed the v2-out-of-order-streaming branch from a9b29e0 to d72b9f7 Compare May 9, 2026 12:14
@Varixo Varixo marked this pull request as draft May 9, 2026 17:07
@maiieul maiieul moved this from Waiting For Review to In progress in Qwik Development May 9, 2026
@Varixo Varixo marked this pull request as ready for review May 9, 2026 20:20
@maiieul maiieul moved this from In progress to Waiting For Review in Qwik Development May 9, 2026
@Varixo Varixo marked this pull request as draft May 10, 2026 06:07
@maiieul maiieul moved this from Waiting For Review to In progress in Qwik Development May 10, 2026
@Varixo Varixo marked this pull request as ready for review May 10, 2026 14:41
@maiieul maiieul moved this from In progress to Waiting For Review in Qwik Development May 10, 2026
@Varixo Varixo force-pushed the v2-out-of-order-streaming branch from ac0875f to 91119b6 Compare May 13, 2026 20:14
Copy link
Copy Markdown
Member

@wmertens wmertens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments


## Out-of-order Streaming

Out-of-order streaming is an optional server rendering mode for `<Suspense>`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be the default when the experimental is enabled.

Out-of-order streaming is an optional server rendering mode for `<Suspense>`.

Server rendering means Qwik creates HTML on the server and sends it to the browser. Streaming means
the browser can receive that HTML in chunks instead of waiting for one complete HTML string.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...HTML string (but still within the same HTTP connection).

...opts,
streaming: {
...opts.streaming,
outOfOrder: { strategy: 'suspense' },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we plan other strategies? Why not a simple boolean and if we want to tweak things later we can optionally accept an object?


### Fallbacks

The fallback is real UI. Choose markup that is useful while the user waits:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the fallback always added to the stream? Worth explaining either way.

waiting. If your fallback has buttons or other event handlers, they can also resume while the
fallback is visible, after the root page state has loaded in the browser.

When the real content arrives, Qwik removes the fallback and inserts the resolved content. The
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qwik hides the fallback, right? Not removes?

while the server is still rendering.

For static site generation, the HTML file is created ahead of time. The user receives the finished
file later, so there is no live server stream to reveal a fallback first.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah and during SSG, OoOS should be disabled of course.

let lastIdx = this.$forwardRefs$.length - 1;
while (lastIdx >= 0 && this.$forwardRefs$[lastIdx] === -1) {
lastIdx--;
private getForwardRefsPayload(): Array<number | string | number[]> | null {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this right, if there is a slow promise first and a faster one later, ooos could send only the faster one and the slow will never be sent?

Copy link
Copy Markdown
Member

@wmertens wmertens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried about forwardRefs, can you write a test with Suspense and a Promise that only resolves after the first chunk, followed by a Promise that resolves before the first chunk?

export const getSegmentVNodeId = (segmentId: string, localIndex: number): number => {
const segmentIndex = parseInt(segmentId, 10) - 1;
const diagonal = segmentIndex + localIndex;
return -((diagonal * (diagonal + 1)) / 2 + localIndex + 1);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how this works, can you add a comment?

@thejackshelton thejackshelton marked this pull request as draft May 19, 2026 05:59
@maiieul maiieul moved this from Waiting For Review to In progress in Qwik Development May 19, 2026
@wmertens wmertens force-pushed the v2-out-of-order-streaming branch from 97ec911 to 91119b6 Compare May 19, 2026 06:10
@Varixo Varixo force-pushed the v2-out-of-order-streaming branch from 8e52f54 to 91119b6 Compare May 20, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

3 participants