sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.11k stars 1.84k forks source link

Prefetch timeout #3787

Open Tal500 opened 2 years ago

Tal500 commented 2 years ago

Describe the problem

SvelteKit include the ability to prefetch pages while the user is hovering over a link. However, a the prefetched data might not be relevant after a period of time, so when the user will click on the link, say after a minute, she will get old data.

Describe the proposed solution

I think the simple solution is to allow to specify timeout. Either allow to specify timeout in a syntax similar to <a sveltekit:prefetch={timeout: (time in seconds)} ...>, or get the timeout from an optional "timeout" property in the return value of load() function, or even support both solutions.

A better/additional aprouch to the simple "timeout" property in my opinion, is to allow the developer to give a predicate: function dataValidity(lastPrefetchedTime): boolean

Alternatives considered

The manual alternative would be to use some custom svelte action in the <a> tag which calls prefetch() manually and call it again if the user hover/click on the link after a certain amount of time.

Sadly, as far as I know, there is not even a way to invalidate the prefetched data manually. (the invalidate() works only for the currently active page acoording to the docs)

Importance

would make my life easier

Additional Information

No response

Conduitry commented 2 years ago

I believe you can control this with a maxage response from that page's load function, and also by the cache header from the API response itself. I don't think this needs to be configurable from the prefetch link itself.

Tal500 commented 2 years ago

I believe you can control this with a maxage response from that page's load function, and also by the cache header from the API response itself. I don't think this needs to be configurable from the prefetch link itself.

According to the docs I understood that it is applied only for HTTP caching feature when it's called on the server side, and is not relevant when the client prefetching data. It is also not available for layouts, I believe because it doesn't make sense to cache a layout.

Rich-Harris commented 2 years ago

Yeah, maxage and cache-control have no effect here (if they did, then sveltekit:prefetch would be useless in the majority of cases, where pages do need to be rendered on demand, but you also want a cheeky headstart). I'm not sure what the correct solution to this would be. It probably belongs on the page itself, but it would probably be more convenient in most cases if it was part of the sveltekit:prefetch attribute value and/or a global (and configurable?) setting.

bluwy commented 2 years ago

Maybe related https://github.com/sveltejs/kit/issues/3633 which suggests setting the timeout in the attribute value too.

Rich-Harris commented 2 years ago

We recently made a change such that instead of returning maxage from load, you return a cache object. One idea that occurs to me is adding a prefetchTimeout property (name subject to bikeshedding, obviously) that, if maxage isn't specified, defaults to the global config.kit.prefetchTimeout (which defaults to some number of milliseconds — say 5000 for the sake of argument).

I think that makes more sense than putting it in the attribute, since there's no reason you'd ever have different values for two links that pointed to the same page.


<script context="module">
  export const load = ({ props }) => ({
    props,
    cache: {
      // for this page, treat data as stale if users hovers on link for >1s
      prefetchTimeout: 1000
    }
  });
</script>
Tal500 commented 1 year ago

any update to this with #5875 ?

Christian-E commented 1 year ago

I have a similar requirement. In fact what I am looking for has been mentioned by @Tal500 in his "Alternatives considered"-section. So I figured I can better add my thoughts to this issue here instead of opening another one. So it can be considered together.

Describe the problem

I need a way to programmatically invalidate prefetched data, so that it is going to be fetched again on subsequent prefetch()-calls, link-hovers or navigation. My usecase is as follows: Think of a Google Drive-like application. You see a list of folders and among other things, you can upload new files to a displayed folder via drag and drop. Now when a user hovers over one of these folders its content is prefetched. But when he now drops new files on that folder and then navigates into it, he does not see the newly added files due to the previous prefetching. In this case I would like to invalidate what has been prefetched before.

Describe the proposed solution

One option would be to allow invalidate() from $app/navigation to also invalidate prefetched data. Or I would need another function that does this.

dummdidumm commented 1 year ago

@Christian-E once #6924 is released invalidate will also invalidate prefetched data.