qwik icon indicating copy to clipboard operation
qwik copied to clipboard

[🐞] Page endpoints (onGet) are invoked during SPA Link prefetching because of q-data.json resulting in potentially HUGE perf implications

Open jordanw66 opened this issue 3 years ago • 2 comments

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

jordanw66 avatar Dec 10 '22 12:12 jordanw66

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.

tzdesign avatar Dec 17 '22 10:12 tzdesign