From 86ef2e2b6289208a27b79413053bff6810553c36 Mon Sep 17 00:00:00 2001 From: Immanuel Calvin Herchenbach <40042006+icalvin102@users.noreply.github.com> Date: Fri, 15 Apr 2022 00:58:02 +0200 Subject: [PATCH] [feat] custom load dependencies (#4536) * [feat] custom load dependencies * [test] custom load dependencies * [docs] custom load dependencies * [changeset] custom load dependencies * [fix] wrong case * Update documentation/docs/04-loading.md Co-authored-by: Rich Harris --- .changeset/breezy-mayflies-yawn.md | 5 +++++ documentation/docs/04-loading.md | 6 ++++++ packages/kit/src/runtime/client/client.js | 12 ++++++++++-- packages/kit/src/runtime/load.js | 17 +++++++++++++---- .../load/change-detection/__layout.svelte | 3 ++- packages/kit/test/apps/basics/test/test.js | 4 ++++ packages/kit/types/index.d.ts | 1 + packages/kit/types/internal.d.ts | 1 + 8 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 .changeset/breezy-mayflies-yawn.md diff --git a/.changeset/breezy-mayflies-yawn.md b/.changeset/breezy-mayflies-yawn.md new file mode 100644 index 000000000000..dc50ecd65e51 --- /dev/null +++ b/.changeset/breezy-mayflies-yawn.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Custom `load` `dependencies` in `LoadOutput` diff --git a/documentation/docs/04-loading.md b/documentation/docs/04-loading.md index a65c36c6e998..4477bcddb6e1 100644 --- a/documentation/docs/04-loading.md +++ b/documentation/docs/04-loading.md @@ -134,3 +134,9 @@ If the `load` function returns a `props` object, the props will be passed to the This will be merged with any existing `stuff` and passed to the `load` functions of subsequent layout and page components. The combined `stuff` is available to components using the [page store](/docs/modules#$app-stores) as `$page.stuff`, providing a mechanism for pages to pass data 'upward' to layouts. + +#### dependencies + +An array of strings representing URLs the page depends on, which can subsequently be used with [`invalidate`](/docs/modules#$app-navigation-invalidate) to cause `load` to rerun. You only need to add them to `dependencies` if you're using a custom API client; URLs loaded with the provided `fetch` function are added automatically. + +URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 97b3167635a4..6789ccd3965f 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -477,6 +477,12 @@ export function create_client({ target, session, base, trailing_slash }) { stuff }; + /** @param dep {string} */ + function add_dependency(dep) { + const { href } = new URL(dep, url); + node.uses.dependencies.add(href); + } + if (props) { // shadow endpoint props means we need to mark this URL as a dependency of itself node.uses.dependencies.add(url.href); @@ -516,8 +522,7 @@ export function create_client({ target, session, base, trailing_slash }) { }, fetch(resource, info) { const requested = typeof resource === 'string' ? resource : resource.url; - const { href } = new URL(requested, url); - node.uses.dependencies.add(href); + add_dependency(requested); return started ? fetch(resource, info) : initial_fetch(resource, info); }, @@ -542,6 +547,9 @@ export function create_client({ target, session, base, trailing_slash }) { node.loaded = normalize(loaded); if (node.loaded.stuff) node.stuff = node.loaded.stuff; + if (node.loaded.dependencies) { + node.loaded.dependencies.forEach(add_dependency); + } } else if (props) { node.loaded = normalize({ props }); } diff --git a/packages/kit/src/runtime/load.js b/packages/kit/src/runtime/load.js index b16097b5763c..c50da95226c2 100644 --- a/packages/kit/src/runtime/load.js +++ b/packages/kit/src/runtime/load.js @@ -9,10 +9,7 @@ export function normalize(loaded) { const status = loaded.status; if (!loaded.error && has_error_status) { - return { - status: status || 500, - error: new Error() - }; + return { status: status || 500, error: new Error() }; } const error = typeof loaded.error === 'string' ? new Error(loaded.error) : loaded.error; @@ -52,6 +49,18 @@ export function normalize(loaded) { } } + if (loaded.dependencies) { + if ( + !Array.isArray(loaded.dependencies) || + loaded.dependencies.some((dep) => typeof dep !== 'string') + ) { + return { + status: 500, + error: new Error('"dependencies" property returned from load() must be of type string[]') + }; + } + } + // TODO remove before 1.0 if (/** @type {any} */ (loaded).context) { throw new Error( diff --git a/packages/kit/test/apps/basics/src/routes/load/change-detection/__layout.svelte b/packages/kit/test/apps/basics/src/routes/load/change-detection/__layout.svelte index 15fd75f299f7..aca5f5bed680 100644 --- a/packages/kit/test/apps/basics/src/routes/load/change-detection/__layout.svelte +++ b/packages/kit/test/apps/basics/src/routes/load/change-detection/__layout.svelte @@ -13,7 +13,8 @@ props: { type, loads: count - } + }, + dependencies: ['custom:change-detection-layout'] }; } diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index 8b150689cc4a..39c5b183276a 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -1197,6 +1197,10 @@ test.describe.parallel('Load', () => { await app.invalidate('/load/change-detection/data.json'); expect(await page.textContent('h1')).toBe('layout loads: 3'); expect(await page.textContent('h2')).toBe('x: b: 2'); + + await app.invalidate('custom:change-detection-layout'); + expect(await page.textContent('h1')).toBe('layout loads: 4'); + expect(await page.textContent('h2')).toBe('x: b: 2'); } }); diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index e77c4d645e76..478cb3c1118a 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -208,6 +208,7 @@ export interface LoadOutput = Record; maxage?: number; + dependencies?: string[]; } export interface Navigation { diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts index 37c0a7fb6d1f..a6496bbef193 100644 --- a/packages/kit/types/internal.d.ts +++ b/packages/kit/types/internal.d.ts @@ -118,6 +118,7 @@ export type NormalizedLoadOutput = { props?: Record | Promise>; stuff?: Record; maxage?: number; + dependencies?: string[]; }; export interface PageData {