[🐞] Page endpoints (onGet) are invoked during SPA Link prefetching because of q-data.json resulting in potentially HUGE perf implications
Which component is affected?
Qwik City (routing)
Describe the bug
When a page has an endpoint like onGet, requests to /<page>/q-data.json will invoke this onGet. The result is that prefetching bundle lists with <Link> from a page route that also has an onGet will necessarily invoke this onGet twice for every SPA navigation. This effectively doubles resource cost on the server via potentially expensive lookups or other actions inside an onGet to get/prepare data.
BIG Perf Implications
Another issue is that hovering various links as your mouse scrolls or just moves around the page would be invoking potentially expensive onGets all over the place for nothing. And on mobile, scrolling down a page would hit everything.
Moving the data to a separate API endpoint and using useMount$ or useResource$ and fetching the data from this separate endpoint will incur no double cost because the page has no onGet and the separate endpoint necessarily doesn't get called when prefetching q-data.json, only once when actually navigating.
Proposed Solution
I don't know too much about the internals on this issue, but I propose prefetching bundle lists via q-data.json is decoupled from calling a page's onGet and that /q-data.json doesn't not return any data (the body field). (and that useEndpoint be adjusted to fetch the page url directly for data instead of the /q-data.json url)
Other considerations would be something like cached q-data.json responses, as mentioned in this PR: https://github.com/BuilderIO/qwik/pull/2314 and using the data from there. However, I don't think this would solve the issue completely because hovering a link will invoke that page's onGet and you may not necessarily click it immediately, instead coming back to it later resulting in either stale data or a wasted request/invocation. (and this doesn't solve the perf implications above)
It's for these reasons my proposed solution above is the ideal one. Prefetching bundles is a must but invoking page endpoints at the same time is a HUGE perf footgun of using them when compared to using separate api endpoints with useMount$ or useResource$ doesn't incur the same problem.
Reproduction
https://stackblitz.com/edit/qwik-starter-v42rfq?file=src/routes/index.tsx
Steps to reproduce
No response
System Info
System:
OS: Linux 6.0 Gentoo Linux
CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
Memory: 51.14 GB / 62.73 GB
Container: Yes
Shell: 5.9 - /bin/zsh
Binaries:
Node: 16.17.1 - ~/.volta/tools/image/node/16.17.1/bin/node
npm: 8.19.2 - ~/.volta/tools/image/npm/8.19.2/bin/npm
npmPackages:
@builder.io/qwik: 0.15.2 => 0.15.2
@builder.io/qwik-city: 0.0.128 => 0.0.128
vite: 3.2.4 => 3.2.4
Additional Information
No response
I really looking forward that this is fixed.
We plan to use prisma directly in some of the components only running on the server.
Right now the spa routing leads also to running Code in the browser.
The new server functions might solve this issue but I like the idea sold to me in the docs.