Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .changeset/tired-deer-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'@qwik.dev/core': minor
---

FEAT: `<Suspense />` allows out-of-order rendering of nested content. If the content is not ready to be rendered, a placeholder is rendered instead. When the content is ready, it streams to the client and replaces the placeholder.

Example:

```tsx
import { component$, Suspense } from '@qwik.dev/core';

export const MyComponent = component$(() => {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<NestedComponent />
</Suspense>
</div>
);
});
```
4 changes: 2 additions & 2 deletions packages/docs/src/routes/api/qwik-server/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
}
],
"kind": "Interface",
"content": "```typescript\nexport interface RenderOptions extends SerializeDocumentOptions \n```\n**Extends:** [SerializeDocumentOptions](#serializedocumentoptions)\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nbase?\n\n\n</td><td>\n\n\n</td><td>\n\nstring \\| ((options: [RenderOptions](#renderoptions)<!-- -->) =&gt; string)\n\n\n</td><td>\n\n_(Optional)_ Specifies the root of the JS files of the client build. Setting a base, will cause the render of the `q:base` attribute in the `q:container` element.\n\n\n</td></tr>\n<tr><td>\n\ncontainerAttributes?\n\n\n</td><td>\n\n\n</td><td>\n\nRecord&lt;string, string&gt;\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\ncontainerTagName?\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n_(Optional)_ When set, the app is serialized into a fragment. And the returned html is not a complete document. Defaults to `html`\n\n\n</td></tr>\n<tr><td>\n\nlocale?\n\n\n</td><td>\n\n\n</td><td>\n\nstring \\| ((options: [RenderOptions](#renderoptions)<!-- -->) =&gt; string)\n\n\n</td><td>\n\n_(Optional)_ Language to use when rendering the document.\n\n\n</td></tr>\n<tr><td>\n\nprefetchStrategy?\n\n\n</td><td>\n\n\n</td><td>\n\n[PrefetchStrategy](#prefetchstrategy) \\| null\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\npreloader?\n\n\n</td><td>\n\n\n</td><td>\n\n[PreloaderOptions](#preloaderoptions) \\| false\n\n\n</td><td>\n\n_(Optional)_ Specifies how preloading is handled. This ensures that code is instantly available when needed.\n\n\n</td></tr>\n<tr><td>\n\nqwikLoader?\n\n\n</td><td>\n\n\n</td><td>\n\n[QwikLoaderOptions](#qwikloaderoptions)\n\n\n</td><td>\n\n_(Optional)_ Specifies how the Qwik Loader is included in the document. This enables interactivity and lazy loading.\n\n`module`<!-- -->: Use a `<script>` tag to load the Qwik Loader. Subsequent page loads will have the script cached and instantly running.\n\n`inline`<!-- -->: This embeds the Qwik Loader script directly in the document. This adds about 3kB before compression, which typically is reduced to about 1.6kB with gzip.\n\n`never`<!-- -->: Do not include the Qwik Loader script. This is mostly useful when embedding multiple containers on the same page.\n\nDefaults to `module`<!-- -->.\n\nNote that the Qwik Loader is absolutely required for Qwik to work. There must be an instance of it loaded for any interactivity to happen.\n\n\n</td></tr>\n<tr><td>\n\nserverData?\n\n\n</td><td>\n\n\n</td><td>\n\nRecord&lt;string, any&gt;\n\n\n</td><td>\n\n_(Optional)_ Metadata that can be retrieved during SSR with `useServerData()`<!-- -->.\n\n\n</td></tr>\n<tr><td>\n\nsnapshot?\n\n\n</td><td>\n\n\n</td><td>\n\nboolean\n\n\n</td><td>\n\n_(Optional)_ Defaults to `true`\n\n\n</td></tr>\n</tbody></table>",
"content": "```typescript\nexport interface RenderOptions extends SerializeDocumentOptions \n```\n**Extends:** [SerializeDocumentOptions](#serializedocumentoptions)\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nbase?\n\n\n</td><td>\n\n\n</td><td>\n\nstring \\| ((options: [RenderOptions](#renderoptions)<!-- -->) =&gt; string)\n\n\n</td><td>\n\n_(Optional)_ Specifies the root of the JS files of the client build. Setting a base, will cause the render of the `q:base` attribute in the `q:container` element.\n\n\n</td></tr>\n<tr><td>\n\ncontainerAttributes?\n\n\n</td><td>\n\n\n</td><td>\n\nRecord&lt;string, string&gt;\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\ncontainerTagName?\n\n\n</td><td>\n\n\n</td><td>\n\nstring\n\n\n</td><td>\n\n_(Optional)_ When set, the app is serialized into a fragment. And the returned html is not a complete document. Defaults to `html`\n\n\n</td></tr>\n<tr><td>\n\nlocale?\n\n\n</td><td>\n\n\n</td><td>\n\nstring \\| ((options: [RenderOptions](#renderoptions)<!-- -->) =&gt; string)\n\n\n</td><td>\n\n_(Optional)_ Language to use when rendering the document.\n\n\n</td></tr>\n<tr><td>\n\nprefetchStrategy?\n\n\n</td><td>\n\n\n</td><td>\n\n[PrefetchStrategy](#prefetchstrategy) \\| null\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\npreloader?\n\n\n</td><td>\n\n\n</td><td>\n\n[PreloaderOptions](#preloaderoptions) \\| false\n\n\n</td><td>\n\n_(Optional)_ Specifies how preloading is handled. This ensures that code is instantly available when needed.\n\n\n</td></tr>\n<tr><td>\n\nqwikLoader?\n\n\n</td><td>\n\n\n</td><td>\n\n[QwikLoaderOptions](#qwikloaderoptions)\n\n\n</td><td>\n\n_(Optional)_ Specifies how the Qwik Loader is included in the document. This enables interactivity and lazy loading.\n\n`module`<!-- -->: Use a `<script>` tag to load the Qwik Loader. Subsequent page loads will have the script cached and instantly running.\n\n`inline`<!-- -->: This embeds the Qwik Loader script directly in the document. This adds about 3kB before compression, which typically is reduced to about 1.6kB with gzip.\n\n`never`<!-- -->: Do not include the Qwik Loader script. This is mostly useful when embedding multiple containers on the same page.\n\nDefaults to `module`<!-- -->.\n\nNote that the Qwik Loader is absolutely required for Qwik to work. There must be an instance of it loaded for any interactivity to happen.\n\n\n</td></tr>\n<tr><td>\n\nserverData?\n\n\n</td><td>\n\n\n</td><td>\n\nRecord&lt;string, any&gt;\n\n\n</td><td>\n\n_(Optional)_ Metadata that can be retrieved during SSR with `useServerData()`<!-- -->.\n\n\n</td></tr>\n<tr><td>\n\nsnapshot?\n\n\n</td><td>\n\n\n</td><td>\n\nboolean\n\n\n</td><td>\n\n_(Optional)_ Defaults to `true`\n\n\n</td></tr>\n<tr><td>\n\nstreaming?\n\n\n</td><td>\n\n\n</td><td>\n\n[StreamingOptions](#streamingoptions)\n\n\n</td><td>\n\n_(Optional)_ Streaming behavior for SSR output.\n\n\n</td></tr>\n</tbody></table>",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/server/types.ts",
"mdFile": "core.renderoptions.md"
},
Expand Down Expand Up @@ -362,7 +362,7 @@
}
],
"kind": "Interface",
"content": "```typescript\nexport interface StreamingOptions \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\ninOrder?\n\n\n</td><td>\n\n\n</td><td>\n\n[InOrderStreaming](#inorderstreaming)\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>",
"content": "```typescript\nexport interface StreamingOptions \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\ninOrder?\n\n\n</td><td>\n\n\n</td><td>\n\n[InOrderStreaming](#inorderstreaming)\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\nsuspenseFallbackDelay?\n\n\n</td><td>\n\n\n</td><td>\n\nnumber\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\nyieldBudget?\n\n\n</td><td>\n\n\n</td><td>\n\nnumber\n\n\n</td><td>\n\n_(Optional)_ Time budget in ms between I/O yields during SSR. Default: 10. Set to 0 to disable.\n\n\n</td></tr>\n</tbody></table>",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/server/types.ts",
"mdFile": "core.streamingoptions.md"
},
Expand Down
45 changes: 45 additions & 0 deletions packages/docs/src/routes/api/qwik-server/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,21 @@ boolean

_(Optional)_ Defaults to `true`

</td></tr>
<tr><td>

streaming?

</td><td>

</td><td>

[StreamingOptions](#streamingoptions)

</td><td>

_(Optional)_ Streaming behavior for SSR output.

</td></tr>
</tbody></table>

Expand Down Expand Up @@ -1288,6 +1303,36 @@ inOrder?

_(Optional)_

</td></tr>
<tr><td>

suspenseFallbackDelay?

</td><td>

</td><td>

number

</td><td>

_(Optional)_

</td></tr>
<tr><td>

yieldBudget?

</td><td>

</td><td>

number

</td><td>

_(Optional)_ Time budget in ms between I/O yields during SSR. Default: 10. Set to 0 to disable.

</td></tr>
</tbody></table>

Expand Down
16 changes: 15 additions & 1 deletion packages/docs/src/routes/api/qwik-testing/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,24 @@
}
],
"kind": "Function",
"content": "```typescript\nexport declare function ssrRenderToDom(jsx: JSXOutput, opts?: {\n debug?: boolean;\n raw?: boolean;\n qwikLoader?: boolean;\n onBeforeResume?: (document: Document) => void;\n}): Promise<{\n container: _DomContainer;\n document: Document;\n vNode: _VNode | null;\n getStyles: () => Record<string, string | string[]>;\n}>;\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\njsx\n\n\n</td><td>\n\nJSXOutput\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\nopts\n\n\n</td><td>\n\n{ debug?: boolean; raw?: boolean; qwikLoader?: boolean; onBeforeResume?: (document: Document) =&gt; void; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\nPromise&lt;{ container: \\_DomContainer; document: Document; vNode: \\_VNode \\| null; getStyles: () =&gt; Record&lt;string, string \\| string\\[\\]&gt;; }&gt;",
"content": "```typescript\nexport declare function ssrRenderToDom(jsx: JSXOutput, opts?: {\n debug?: boolean;\n raw?: boolean;\n qwikLoader?: boolean;\n streaming?: StreamingOptions;\n onBeforeResume?: (document: Document) => void;\n}): Promise<{\n container: _DomContainer;\n document: Document;\n vNode: _VNode | null;\n getStyles: () => Record<string, string | string[]>;\n}>;\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\njsx\n\n\n</td><td>\n\nJSXOutput\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\nopts\n\n\n</td><td>\n\n{ debug?: boolean; raw?: boolean; qwikLoader?: boolean; streaming?: [StreamingOptions](#streamingoptions)<!-- -->; onBeforeResume?: (document: Document) =&gt; void; }\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\nPromise&lt;{ container: \\_DomContainer; document: Document; vNode: \\_VNode \\| null; getStyles: () =&gt; Record&lt;string, string \\| string\\[\\]&gt;; }&gt;",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/testing/rendering.unit-util.tsx",
"mdFile": "core.ssrrendertodom.md"
},
{
"name": "StreamingOptions",
"id": "streamingoptions",
"hierarchy": [
{
"name": "StreamingOptions",
"id": "streamingoptions"
}
],
"kind": "Interface",
"content": "```typescript\nexport interface StreamingOptions \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\ninOrder?\n\n\n</td><td>\n\n\n</td><td>\n\nInOrderStreaming\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\nsuspenseFallbackDelay?\n\n\n</td><td>\n\n\n</td><td>\n\nnumber\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n<tr><td>\n\nyieldBudget?\n\n\n</td><td>\n\n\n</td><td>\n\nnumber\n\n\n</td><td>\n\n_(Optional)_ Time budget in ms between I/O yields during SSR. Default: 10. Set to 0 to disable.\n\n\n</td></tr>\n</tbody></table>",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/server/types.ts",
"mdFile": "core.streamingoptions.md"
},
{
"name": "superParent",
"id": "elementfixture-superparent",
Expand Down
75 changes: 74 additions & 1 deletion packages/docs/src/routes/api/qwik-testing/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ export declare function ssrRenderToDom(
debug?: boolean;
raw?: boolean;
qwikLoader?: boolean;
streaming?: StreamingOptions;
onBeforeResume?: (document: Document) => void;
},
): Promise<{
Expand Down Expand Up @@ -489,7 +490,7 @@ opts

</td><td>

\{ debug?: boolean; raw?: boolean; qwikLoader?: boolean; onBeforeResume?: (document: Document) =&gt; void; }
\{ debug?: boolean; raw?: boolean; qwikLoader?: boolean; streaming?: [StreamingOptions](#streamingoptions); onBeforeResume?: (document: Document) =&gt; void; }

</td><td>

Expand All @@ -504,6 +505,78 @@ Promise&lt;\{ container: \_DomContainer; document: Document; vNode: \_VNode \| n

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/testing/rendering.unit-util.tsx)

<h2 id="streamingoptions">StreamingOptions</h2>

```typescript
export interface StreamingOptions
```

<table><thead><tr><th>

Property

</th><th>

Modifiers

</th><th>

Type

</th><th>

Description

</th></tr></thead>
<tbody><tr><td>

inOrder?

</td><td>

</td><td>

InOrderStreaming

</td><td>

_(Optional)_

</td></tr>
<tr><td>

suspenseFallbackDelay?

</td><td>

</td><td>

number

</td><td>

_(Optional)_

</td></tr>
<tr><td>

yieldBudget?

</td><td>

</td><td>

number

</td><td>

_(Optional)_ Time budget in ms between I/O yields during SSR. Default: 10. Set to 0 to disable.

</td></tr>
</tbody></table>

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/server/types.ts)

<h2 id="elementfixture-superparent">superParent</h2>

```typescript
Expand Down
28 changes: 28 additions & 0 deletions packages/docs/src/routes/api/qwik/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -2241,6 +2241,34 @@
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts",
"mdFile": "core.ssrstreamwriter.md"
},
{
"name": "Suspense",
"id": "suspense",
"hierarchy": [
{
"name": "Suspense",
"id": "suspense"
}
],
"kind": "Variable",
"content": "```typescript\nSuspense: FunctionComponent<SuspenseProps>\n```",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts",
"mdFile": "core.suspense.md"
},
{
"name": "SuspenseProps",
"id": "suspenseprops",
"hierarchy": [
{
"name": "SuspenseProps",
"id": "suspenseprops"
}
],
"kind": "TypeAlias",
"content": "```typescript\nexport type SuspenseProps = {\n fallback?: JSXOutput;\n children?: JSXOutput;\n};\n```\n**References:** [JSXOutput](#jsxoutput)",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts",
"mdFile": "core.suspenseprops.md"
},
{
"name": "SVGAttributes",
"id": "svgattributes",
Expand Down
21 changes: 21 additions & 0 deletions packages/docs/src/routes/api/qwik/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4914,6 +4914,27 @@ Description

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts)

<h2 id="suspense">Suspense</h2>

```typescript
Suspense: FunctionComponent<SuspenseProps>;
```

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts)

<h2 id="suspenseprops">SuspenseProps</h2>

```typescript
export type SuspenseProps = {
fallback?: JSXOutput;
children?: JSXOutput;
};
```

**References:** [JSXOutput](#jsxoutput)

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/jsx/utils.public.ts)

<h2 id="svgattributes">SVGAttributes</h2>

The TS types don't include the SVG attributes so we have to define them ourselves
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@
"_noopQrlDEV",
"_regSymbol",
"_verifySerializable",
"_walkJSX",
"_ssrDiff",
"_wrapSignal",
"_wrapStore",
"component$",
Expand Down
Loading
Loading