[✨] Allow loaders to be refetched programmatically and configure if they should refetch when an action is run #171
Replies: 20 comments 8 replies
-
I am new to Qwik and was looking for something like this to cache the loaders and not re-run them. Ideally, I prefer a similar solution to Next.js, where they parse the cache header to set this up automatically or give you a way to set up the timer on when to invalidate this cache. Do you know if Qwik already parses the cache header for the loader$ to effectively deliver your 1st requirement? |
Beta Was this translation helpful? Give feedback.
-
That is a fair point. However, it doesn't address the extra data that's going to be sent from the server back to the client even if the loader is cached on the server. Which is about 150KB in our case, nearly all of which doesn't need to be sent again. Just tested the caching, doesn't seem like it's supported(the loaders and actions didn't work on stackblitz so you'll probably need to copy the code): |
Beta Was this translation helpful? Give feedback.
-
I was hoping that the cache header would trickle all that way so that re-fetching from the client side would only yield a no-change response. Thank you for testing it out! It seems this is quite a missed opportunity. |
Beta Was this translation helpful? Give feedback.
-
The setup of loaders and actions doesn't really work that way. Once an action is finished running a q-data.json file is sent back to the browser which contains the result of the action and a rerun of all the loaders. This is what I'm referring to in ask 1 |
Beta Was this translation helpful? Give feedback.
-
We want to solve this problem, but remember that actions can be submits, ie full page reloads. In this case the loaders will need to run, just like any page refresh! |
Beta Was this translation helpful? Give feedback.
-
We could do:
We will looking into both strategies! so please, keep the conversation going, i would love to understand better how you plan to use this APIs. We will collect all this feedback and try to put it together! |
Beta Was this translation helpful? Give feedback.
-
That’s a good point. I guess maybe it makes more sense to configure the “strategy” of the action instead of the loader and the strategy could either be rerun all the loaders with a full reload or only return the data from the action. The specific problem I was hoping this would solve is handling authentication state. We are currently fetching the user in a loader and storing it in a context(so we can update the context when the user logs out, all from the client), but it would be ideal to treat the loader as the single source of truth. The other way I could do it is to run an action to log out the user, which would rerun the user loader. This suffered from the first problem of sending a lot of data(about 150kb) and making many unnecessary requests due to the number of loaders we have. That said, the programmatic loaders would pretty much solve this because we could log out and then refetch only that loader. But I could see use cases where it’s unnecessary for actions to cause full reloads. So adding a strategy to actions and programmatic loaders would allow the control needed to only reload what’s needed. Such as submitting a form as an action and then refetching one loader programmatically. |
Beta Was this translation helpful? Give feedback.
-
The ability to control when an action$ triggers some, none or all loaders would be helpful. For example, if you have a login form and the users login was successful, fire all loaders. But if the user login fails, fire none or only specific loaders. |
Beta Was this translation helpful? Give feedback.
-
@manucorporat I'm using a server$ function, how can I trigger a full page reload with it? |
Beta Was this translation helpful? Give feedback.
-
This issue has become quite a bottleneck for my app. Submitting a form in a nested route causes all routeLoaders in the parent layout files to run which in turn makes the response of my actions really slow. |
Beta Was this translation helpful? Give feedback.
-
Bundled some duplicates. Generally speaking, the desired caching behavior seems to mostly be "forever". So if a routeloader ran once, cache it and never run it again while navigating. Maybe this can be achieved in the serviceworker, adding SSR'd routerloaders into the browser cache? |
Beta Was this translation helpful? Give feedback.
-
@wmertens It's true if the |
Beta Was this translation helpful? Give feedback.
-
Since I have read about the I you want enforce refetching a route loader when SPA navigate to the page the loader related with, you can put a cache buster parameter to the href of the component. |
Beta Was this translation helpful? Give feedback.
-
If the route loader is a pure function, the cache buster parameter can be inferred from the arguments of the function. |
Beta Was this translation helpful? Give feedback.
-
We moved this issue to |
Beta Was this translation helpful? Give feedback.
-
@gioboa Is the current intended behavior that when any |
Beta Was this translation helpful? Give feedback.
-
In our situation, we have an interactive map where users can explore and navigate it. Everytime they move in the map, the current URL is updated to keep track of where they were (similar to what Google Maps does). Unfortunately, when this occurs, all the So, simply joining this thread for another use case and sharing that having more fine-grained control on caching/deciding when to re-execute a |
Beta Was this translation helpful? Give feedback.
-
related: we disabled caching for q-data.json and I think it was a mistake QwikDev/qwik#7536 |
Beta Was this translation helpful? Give feedback.
-
The design of bundling all loaders into a single q-data means that they're all fetched with every prefetch, navigation, or action. I think this can be solved by giving us control over how the q-data objects are bundled and allowing more than 1 q-data requests for each route. Then, let the browser cache requests based on the cach-control header and also make sure we deduplicate requests if there are multiple of the same requests at the same time for different routes sharing a q-data. I propose introducing a new routeLoader$ config option: bundle: undefined | 'default' | 'self' // This is a standard routeLoader$ - there are no breaking changes.
// This is the same as using bundle: 'default'
// All routeLoaders defined like this still get bundled together into the same q-data request
const useStandard = routeLoader$(() => {
return data
})
// This routeLoader$ gets bundled into its own q-data and can have its own cache control header.
const useStatic = routeLoader$(({ cacheControl }) => {
cacheControl({ private: true, maxAge: 1800, staleWhileRevalidate: true })
return data
}, {
bundle: 'self',
}) This could even be extended at some point to allow bundling a routeLoader$ with another routerLoader, but I don't see much benefit here: // Bundled with the useStatic loader above so it will share the same cacheControl settings
const useStatic2 = routeLoader$(() => {
return data
}, {
bundle: useStatic,
}) |
Beta Was this translation helpful? Give feedback.
-
closing in favor of #246 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Is your feature request related to a problem?
Yes. We have a pretty complex page which requires various api calls which we use a different loader for each. Not sure if this is feasible but it would be nice to
Describe the solution you'd like
The strategies could be 'manual' or 'automatic' or maybe something more clear. But automatic would rerun when actions are called and manual would not. Default could be 'automatic' since that's the way it currently works now.
Additionally a loader can be rerun by calling
getProductData.refresh()
I'm sure the semantics with the naming could be improved. But if these additions could be made to allow more control over the loaders that would make the qwik data fetching even more incredible
Describe alternatives you've considered
The alternative I guess is to leave it the way it is? I'm not sure if this is even feasible as I'm not super familiar with the lower level implementation of loaders and actions
Additional context
No response
Beta Was this translation helpful? Give feedback.
All reactions