diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/README.md b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/README.md new file mode 100644 index 000000000..cc0cf15c4 --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/README.md @@ -0,0 +1,55 @@ +--- +title: Streaming data +path: /blog/welcome +--- + +Ordinarily, SvelteKit will load all the data your page needs _before_ rendering it. In general this provides a better user experience than showing loading spinners and skeleton UI everywhere. But sometimes you know that some data will be slow to load, and that it would be better to render the rest of the page instead of waiting for it. In these cases, we can return promises from `load` functions. + +In this exercise, we've added comments to the blog from [earlier](page-data), via a `getComments` function in `src/lib/server/data.js` with a simulated delay. + +Update `src/routes/blog/[slug]/+page.server.js` to load the comments: + +```js +/// file: src/routes/blog/[slug]/+page.server.js +import { error } from '@sveltejs/kit'; +import * as db from '$lib/server/data.js'; + +export function load({ params }) { + const post = db.getPost(params.slug); + + if (!post) throw error(404); + + return { + post, ++++ promises: { + comments: db.getComments(params.slug) + }+++ + }; +} +``` + +> If `comments` is a top-level property of the returned object, SvelteKit will automatically await it. For that reason, we must nest it inside an object. Here, we've called that object `promises`, but the name is not important. + +Inside `src/routes/blog/[slug]/+page.svelte` we can now use an [`{#await ...}`](await-blocks) block to render placeholder UI while the data loads: + +```svelte +/// file: src/routes/blog/[slug]/+page.svelte + + +

{data.post.title}

+
{@html data.post.content}
+ ++++

Comments

+ +{#await data.promises.comments} +

loading comments...

+{:then comments} + {#each comments as comment} +

{comment.author} {comment.content}

+ {/each} +{:catch} +

failed to load comments

+{/await}+++ +``` \ No newline at end of file diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/lib/server/data.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/lib/server/data.js new file mode 100644 index 000000000..16e5fdc2d --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/lib/server/data.js @@ -0,0 +1,75 @@ +export function getSummaries() { + return posts.map((post) => ({ + slug: post.slug, + title: post.title + })); +} + +export function getPost(slug) { + const post = posts.find((post) => post.slug === slug); + + if (post) { + return { + slug: post.slug, + title: post.title, + content: post.content + }; + } +} + +export async function getComments(slug) { + // simulate delay + await new Promise((fulfil) => setTimeout(fulfil, 1000)); + + const post = posts.find((post) => post.slug === slug); + return post?.comments; +} + +const posts = [ + { + slug: 'welcome', + title: + 'Welcome to the Aperture Science computer-aided enrichment center', + content: + '

We hope your brief detention in the relaxation vault has been a pleasant one.

Your specimen has been processed and we are now ready to begin the test proper.

', + comments: [ + { + author: 'GLaDOS', + content: "This cake is great! It's so delicious and moist!" + }, + { + author: 'Doug', + content: 'The cake is a lie' + } + ] + }, + + { + slug: 'safety', + title: 'Safety notice', + content: + '

While safety is one of many Enrichment Center Goals, the Aperture Science High Energy Pellet, seen to the left of the chamber, can and has caused permanent disabilities, such as vaporization. Please be careful.

', + comments: [ + { + author: 'Cave', + content: "Science isn't about WHY, it's about WHY NOT!" + } + ] + }, + + { + slug: 'cake', + title: 'This was a triumph', + content: "

I'm making a note here: HUGE SUCCESS.

", + comments: [ + { + author: 'GLaDOS', + content: "It's hard to overstate my satisfaction." + }, + { + author: 'GLaDOS', + content: 'Aperture Science. We do what we must because we can.' + } + ] + } +]; \ No newline at end of file diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+layout.svelte new file mode 100644 index 000000000..307ba0a2c --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+layout.svelte @@ -0,0 +1,6 @@ + + + diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+page.svelte new file mode 100644 index 000000000..0a88878c3 --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/+page.svelte @@ -0,0 +1 @@ +

home

diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+layout.server.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+layout.server.js new file mode 100644 index 000000000..3dec19083 --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+layout.server.js @@ -0,0 +1,7 @@ +import * as db from '$lib/server/data.js'; + +export function load() { + return { + summaries: db.getSummaries() + }; +} diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+page.svelte new file mode 100644 index 000000000..4e5bc4a2e --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/+page.svelte @@ -0,0 +1,11 @@ + + +

blog

+ + diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+layout.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+layout.svelte new file mode 100644 index 000000000..d455eefce --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+layout.svelte @@ -0,0 +1,30 @@ + + +
+
+ +
+ + +
+ + diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.server.js new file mode 100644 index 000000000..439bf826d --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.server.js @@ -0,0 +1,12 @@ +import { error } from '@sveltejs/kit'; +import * as db from '$lib/server/data.js'; + +export function load({ params }) { + const post = db.getPost(params.slug); + + if (!post) throw error(404); + + return { + post + }; +} diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.svelte new file mode 100644 index 000000000..e54908bf9 --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-a/src/routes/blog/[slug]/+page.svelte @@ -0,0 +1,6 @@ + + +

{data.post.title}

+
{@html data.post.content}
diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.server.js new file mode 100644 index 000000000..1d6d70497 --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.server.js @@ -0,0 +1,15 @@ +import { error } from '@sveltejs/kit'; +import * as db from '$lib/server/data.js'; + +export function load({ params }) { + const post = db.getPost(params.slug); + + if (!post) throw error(404); + + return { + post, + promises: { + comments: db.getComments(params.slug) + } + }; +} diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.svelte new file mode 100644 index 000000000..58ef1c9cd --- /dev/null +++ b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-streaming/app-b/src/routes/blog/[slug]/+page.svelte @@ -0,0 +1,18 @@ + + +

{data.post.title}

+
{@html data.post.content}
+ +

Comments

+ +{#await data.promises.comments} +

loading comments...

+{:then comments} + {#each comments as comment} +

{comment.author} {comment.content}

+ {/each} +{:catch} +

failed to load comments

+{/await} \ No newline at end of file diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/README.md b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/README.md similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/README.md rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/README.md diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/+layout.js similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/+layout.js rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/+layout.js diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/+layout.svelte similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/+layout.svelte rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/+layout.svelte diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/[...timezone]/+page.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/[...timezone]/+page.js similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/[...timezone]/+page.js rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/[...timezone]/+page.js diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/[...timezone]/+page.svelte similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/[...timezone]/+page.svelte rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/[...timezone]/+page.svelte diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/api/now/+server.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/api/now/+server.js similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-a/src/routes/api/now/+server.js rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-a/src/routes/api/now/+server.js diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-b/src/routes/[...timezone]/+page.svelte similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/04-invalidation/app-b/src/routes/[...timezone]/+page.svelte rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-invalidation/app-b/src/routes/[...timezone]/+page.svelte diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/README.md b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/README.md similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/README.md rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/README.md diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/app-b/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/app-b/src/routes/+layout.js similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/app-b/src/routes/+layout.js rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/app-b/src/routes/+layout.js diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/05-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/README.md b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/README.md similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/README.md rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/README.md diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/app-b/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/app-b/src/routes/+layout.js similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/app-b/src/routes/+layout.js rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/app-b/src/routes/+layout.js diff --git a/content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte similarity index 100% rename from content/tutorial/04-advanced-sveltekit/05-advanced-loading/06-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte rename to content/tutorial/04-advanced-sveltekit/05-advanced-loading/07-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte