-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat: allow for fine grained invalidation of search params #11066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 16 commits
364c2a4
988bcb6
0e51f81
47b7b9b
ac11e75
d3b4d2f
e0c67f8
fe6b814
4968f42
5373dfa
ad8d2c6
bbc62f1
5b6b253
d3a9ae8
8fc1328
d470608
9e04dad
92c45f2
e8bb9f1
f4975dd
6172001
51c20ab
23ea3f5
56b50d5
d72cac9
ff8b4bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@sveltejs/kit": minor | ||
--- | ||
|
||
feat: allow for fine grained invalidation of search params |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,9 +69,11 @@ function native_navigation(url) { | |
/** | ||
* @param {import('./types.js').SvelteKitApp} app | ||
* @param {HTMLElement} target | ||
* @param {boolean} fine_grained_search_params_invalidation | ||
* @returns {import('./types.js').Client} | ||
*/ | ||
export function create_client(app, target) { | ||
export function create_client(app, target, fine_grained_search_params_invalidation) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a reason to pass this into create_client as a param. This could be done using define and that'd reduce the complexity of the config quite a bit on the server side. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think i've ever heard of define...do you have a link to some resource i can look into? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh i think now i realized it's from vite...exploring this a bit |
||
// TODO remove fine_grained_search_params_invalidation after 2.0 | ||
const routes = parse(app); | ||
|
||
const default_layout_loader = app.nodes[0]; | ||
|
@@ -443,7 +445,8 @@ export function create_client(app, target) { | |
params: new Set(), | ||
parent: false, | ||
route: false, | ||
url: false | ||
url: false, | ||
search_params: new Set() | ||
}; | ||
|
||
const node = await loader(); | ||
|
@@ -478,9 +481,20 @@ export function create_client(app, target) { | |
} | ||
}), | ||
data: server_data_node?.data ?? null, | ||
url: make_trackable(url, () => { | ||
uses.url = true; | ||
}), | ||
url: make_trackable( | ||
url, | ||
() => { | ||
uses.url = true; | ||
}, | ||
(search_param) => { | ||
// TODO remove fine_grained_search_params_invalidation after 2.0 | ||
if (fine_grained_search_params_invalidation) { | ||
uses.search_params.add(search_param); | ||
} else { | ||
uses.url = true; | ||
} | ||
} | ||
), | ||
async fetch(resource, init) { | ||
/** @type {URL | string} */ | ||
let requested; | ||
|
@@ -576,10 +590,18 @@ export function create_client(app, target) { | |
* @param {boolean} parent_changed | ||
* @param {boolean} route_changed | ||
* @param {boolean} url_changed | ||
* @param {Set<string>} search_params_changed | ||
* @param {import('types').Uses | undefined} uses | ||
* @param {Record<string, string>} params | ||
*/ | ||
function has_changed(parent_changed, route_changed, url_changed, uses, params) { | ||
function has_changed( | ||
parent_changed, | ||
route_changed, | ||
url_changed, | ||
search_params_changed, | ||
uses, | ||
params | ||
) { | ||
if (force_invalidation) return true; | ||
|
||
if (!uses) return false; | ||
|
@@ -588,6 +610,10 @@ export function create_client(app, target) { | |
if (uses.route && route_changed) return true; | ||
if (uses.url && url_changed) return true; | ||
|
||
for (const tracked_params of uses.search_params) { | ||
if (search_params_changed.has(tracked_params)) return true; | ||
} | ||
|
||
for (const param of uses.params) { | ||
if (params[param] !== current.params[param]) return true; | ||
} | ||
|
@@ -610,6 +636,26 @@ export function create_client(app, target) { | |
return null; | ||
} | ||
|
||
/** | ||
* | ||
* @param {URL} [old_url] | ||
* @param {URL} [new_url] | ||
*/ | ||
function check_search_params_changed(old_url, new_url) { | ||
const changed = new Set(); | ||
const new_search_params = new URLSearchParams(new_url?.searchParams); | ||
for (const [key, value] of old_url?.searchParams?.entries?.() ?? []) { | ||
if (new_search_params.get(key) !== value) { | ||
changed.add(key); | ||
} | ||
new_search_params.delete(key); | ||
paoloricciuti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
for (const [key] of new_search_params) { | ||
changed.add(key); | ||
} | ||
return changed; | ||
} | ||
|
||
/** | ||
* @param {import('./types.js').NavigationIntent} intent | ||
* @returns {Promise<import('./types.js').NavigationResult>} | ||
|
@@ -631,9 +677,9 @@ export function create_client(app, target) { | |
|
||
/** @type {import('types').ServerNodesResponse | import('types').ServerRedirectNode | null} */ | ||
let server_data = null; | ||
|
||
const url_changed = current.url ? id !== current.url.pathname + current.url.search : false; | ||
const route_changed = current.route ? route.id !== current.route.id : false; | ||
const search_params_changed = check_search_params_changed(current.url, url); | ||
|
||
let parent_invalid = false; | ||
const invalid_server_nodes = loaders.map((loader, i) => { | ||
|
@@ -642,7 +688,14 @@ export function create_client(app, target) { | |
const invalid = | ||
!!loader?.[0] && | ||
(previous?.loader !== loader[1] || | ||
has_changed(parent_invalid, route_changed, url_changed, previous.server?.uses, params)); | ||
has_changed( | ||
parent_invalid, | ||
route_changed, | ||
url_changed, | ||
search_params_changed, | ||
previous.server?.uses, | ||
params | ||
)); | ||
|
||
if (invalid) { | ||
// For the next one | ||
|
@@ -685,7 +738,14 @@ export function create_client(app, target) { | |
const valid = | ||
(!server_data_node || server_data_node.type === 'skip') && | ||
loader[1] === previous?.loader && | ||
!has_changed(parent_changed, route_changed, url_changed, previous.universal?.uses, params); | ||
!has_changed( | ||
parent_changed, | ||
route_changed, | ||
url_changed, | ||
search_params_changed, | ||
previous.universal?.uses, | ||
params | ||
); | ||
if (valid) return previous; | ||
|
||
parent_changed = true; | ||
|
@@ -1954,7 +2014,8 @@ function deserialize_uses(uses) { | |
params: new Set(uses?.params ?? []), | ||
parent: !!uses?.parent, | ||
route: !!uses?.route, | ||
url: !!uses?.url | ||
url: !!uses?.url, | ||
search_params: new Set(uses?.search_params ?? []) | ||
}; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.