diff --git a/packages/kit/src/runtime/app/navigation.js b/packages/kit/src/runtime/app/navigation.js index e1dfbc36a90b..b245089e9196 100644 --- a/packages/kit/src/runtime/app/navigation.js +++ b/packages/kit/src/runtime/app/navigation.js @@ -14,6 +14,7 @@ export const goto = import.meta.env.SSR ? guard('goto') : goto_; export const invalidate = import.meta.env.SSR ? guard('invalidate') : invalidate_; export const prefetch = import.meta.env.SSR ? guard('prefetch') : prefetch_; export const prefetchRoutes = import.meta.env.SSR ? guard('prefetchRoutes') : prefetchRoutes_; +export const invalidate = import.meta.env.SSR ? guard('invalidate') : invalidate_; /** * @type {import('$app/navigation').goto} @@ -46,3 +47,8 @@ async function prefetchRoutes_(pathnames) { await Promise.all(promises); } + +async function invalidate_(resource) { + const info = router.parse(new URL(location.href)); + return router.renderer.update({ ...info, invalidates: resource }); +} diff --git a/packages/kit/src/runtime/client/renderer.js b/packages/kit/src/runtime/client/renderer.js index 55945edaabdf..9ce381f8bb95 100644 --- a/packages/kit/src/runtime/client/renderer.js +++ b/packages/kit/src/runtime/client/renderer.js @@ -322,7 +322,12 @@ export class Renderer { } } - const result = await this._load({ route, path: info.path, query: info.query }); + const result = await this._load({ + route, + path: info.path, + query: info.query, + invalidates: info.invalidates + }); if (result) return result; } @@ -418,7 +423,8 @@ export class Renderer { path: false, query: false, session: false, - context: false + context: false, + invalidates: new Set() }, loaded: null, context @@ -461,7 +467,10 @@ export class Renderer { node.uses.context = true; return { ...context }; }, - fetch: this.started ? fetch : initial_fetch + fetch(resource, info) { + node.uses.invalidates.add(resource); + return this.started ? fetch(resource, info) : initial_fetch(resource, info); + } }; if (error) { @@ -485,7 +494,7 @@ export class Renderer { * @param {import('./types').NavigationCandidate} selected * @returns {Promise} */ - async _load({ route, path, query }) { + async _load({ route, path, query, invalidates }) { const hash = `${path}?${query}`; if (this.cache.has(hash)) { @@ -538,6 +547,7 @@ export class Renderer { changed.params.some((param) => previous.uses.params.has(param)) || (changed.query && previous.uses.query) || (changed.session && previous.uses.session) || + (invalidates && previous.uses.invalidates.has(invalidates)) || (context_changed && previous.uses.context); if (changed_since_last_render) { diff --git a/packages/kit/src/runtime/client/types.d.ts b/packages/kit/src/runtime/client/types.d.ts index c7affca44fed..33e90d44a376 100644 --- a/packages/kit/src/runtime/client/types.d.ts +++ b/packages/kit/src/runtime/client/types.d.ts @@ -2,40 +2,41 @@ import { Page, LoadOutput } from '../../../types/page'; import { CSRComponent, CSRRoute } from '../../../types/internal'; export type NavigationInfo = { - id: string; - routes: CSRRoute[]; - path: string; - query: URLSearchParams; + id: string; + routes: CSRRoute[]; + path: string; + query: URLSearchParams; }; export type NavigationCandidate = { - route: CSRRoute; - path: string; - query: URLSearchParams; + route: CSRRoute; + path: string; + query: URLSearchParams; }; export type NavigationResult = { - reload?: boolean; - redirect?: string; - state?: NavigationState; - props?: Record; + reload?: boolean; + redirect?: string; + state?: NavigationState; + props?: Record; }; export type BranchNode = { - module: CSRComponent; - loaded: LoadOutput; - uses: { - params: Set; - path: boolean; - query: boolean; - session: boolean; - context: boolean; - }; - context: Record; + module: CSRComponent; + loaded: LoadOutput; + uses: { + params: Set; + path: boolean; + query: boolean; + session: boolean; + context: boolean; + invalidates: Set; + }; + context: Record; }; export type NavigationState = { - page: Page; - branch: BranchNode[]; - session_id: number; + page: Page; + branch: BranchNode[]; + session_id: number; };