Comments (7)
That feels correct, the fetchExchange is an async exchange while the ssr
is meant to be synchronous so the order is [...synchronous, ...async]
. In the current order there would also never be an ssr-result saved to the ssrExchange. Why do you need two fetchExchanges?
from urql.
That feels correct, the fetchExchange is an async exchange while the
ssr
is meant to be synchronous so the order is[...synchronous, ...async]
. In the current order there would also never be an ssr-result saved to the ssrExchange. Why do you need two fetchExchanges?
according to docs, persistedExchange
DOES NOT replaces fetchExchange
- so no, there are NOT 2 fetch exchanges.
from urql.
The reproduction here doesn't reproduce the issue.
However, to explain what's going on. For this to become a problem a couple of things need to be the case. Mainly, the exchange(s) after the persistedExchange
must be:
- replying synchronously; and
- must always respond with
PersistedQueryNotFound
If both of these are true then you'll get aRangeError
as thepersistedExchange
will never terminate. We can add a protection for that, but just pointing out that this is likely usage error.
Unrelatedly, some notes on the reproduction, which seems to behave fine in its current state:
- there's no cache, so I can't guarantee much in terms of client-side non-duplicate requests. Please note that the
ssrExchange
IS NOT a cache. While uncached usage ofurql
should work there are some caveats, so I'd consider this an advanced use-case. - the example hydrates the string
'urql'
into initial state, so do take care that this doesn't actually get misused or misparsed. - it doesn't actually hook into Nuxt's lifecycles, uses the SSR state, or uses
await useQuery
as far as I can tell. We have some threads on setup for this in issues/discussions, I believe, but overall, I'm not well versed in Nuxt so I can't check against that. So, just a note that this looks off
Overall, while it shouldn't matter whether you place persistedExchange
in front of or after ssrExchange
, since they're both synchronous. The reversal doesn't matter and neither will lead to duplicate requests per se.
I suspect what you might have seen is an Automatic Persisted Query miss, hence the request repeating? As long as the operation.key
matches, the ssrExchange
will be used.
However, the ssrExchange
will only make its results available to the Client
once on the client-side, since it's not a cache but just a "replay exchange" for prior results from the server-side. So, if for any reason you repeat the query (e.g. client navigation / updates, or ssrExchange
hydrating a PersistedQueryNotFound
error) then the ssrExchange
will not respond for the given operation.key
either way.
I hope that clarifies this, but for now I'll mark this issue as “needs more info” ✌️
However, I don't currently see anything that looks off, except for potentially no specific error message being available for when the persistedExchange
might receive PersistedQueryNotFound
continuously 🤔
Edit: I've just seen that you meant the server-side log contains the mentioned error. My bad! They were hidden from me, so I didn't check or notice them, since the client served just fine.
I just realised what's going on here,
I've mentioned it above.
I suspect what you might have seen is an Automatic Persisted Query miss, hence the request repeating? As long as the
operation.key
matches, thessrExchange
will be used.
However, thessrExchange
will only make its results available to theClient
once on the client-side, since it's not a cache but just a "replay exchange" for prior results from the server-side. So, if for any reason you repeat the query (e.g. client navigation / updates, orssrExchange
hydrating aPersistedQueryNotFound
error) then thessrExchange
will not respond for the givenoperation.key
either way.
The ssrExchange
will still replay results on the server-side. Hence the PersistedQueryNotFound
error is replayed.
The client still renders likely since the rest of the setup isn't actually handling SSR for the client-side, so basically, it's as if you're rendering HTML in Nuxt SSR mode and then discarding the result and building a completely independent result on the client-side.
Long story short, the stacktraced error in the Node process (i.e. server-side) can be completely explained by the above, the other issues you're describing are basically expected behaviour given the setup (re. the prior list I provided)
So, I'll close this out and will look into whether we can at least make this clearer and issue a warning when a loop occurs instead
from urql.
isn't the idea of ssr exchange - when client hydrates - to NOT execute queries again, because they already have data sent from server?
If I remove persisted exchange and leave ssrExchange - client does NOT executes queries.
from urql.
See edit; I missed what's going on on the server-side, and that explains the error there, while the rest can be explained by missing setup code, as long as the reproduction is basically what's being run in your case too.
isn't the idea of ssr exchange - when client hydrates - to NOT execute queries again, because they already have data sent from server?
Not necessarily, no. The ssrExchange
has a different priority. Its priority is to make sure that, as long as it's hydrated on the client-side correctly, the render/hydration that the client-side performs uses the same data that the server used.
This is a subtly different goal. After hydration, we don't expect it to act like a cache and that's why it only returns a result once. It basically replaces the fetchExchange
for results that the server has already used/seen once.
The problem with persistedExchange
is that, as long as your persistedExchange
is used in front of the ssrExchange
the ssrExchange
“sees” your persisted errors. Meaning, it will treat them as the canonical result. This then means that we allow this result to be rendered server-side.
The ssrExchange
is basically a single-time “snapshot” of what results your server uses to render the SSR result.
Edit 2: You're likely aware of this, but just so I address this too, since I forgot. If you add random data to the query, its key changes on every render, i.e. it'll also be different between client-side and server-side and a match can never occur between the two
from urql.
Edit 2: You're likely aware of this, but just so I address this too, since I forgot. If you add random data to the query, its key changes on every render, i.e. it'll also be different between client-side and server-side and a match can never occur between the two
Yeah, that was only to reproduce nodejs error.
I've tested now and indeed it re-executes query on client-side if there is only ssrExchange, however it does not when you have ssrExchange and then persistedExchange. If I remove persistedExchange - it always re-execute query, even if there is normalized cache. I always though that ssrExchange will prevent client re-execution.
In that case - what's the best way to prevent client-side to execute queries that SSR already executed ?
from urql.
I'm adding a dev-time warning to this, since it's a very specific case that's clearly just confusing and hard to grasp given the error.
If I remove persistedExchange - it always re-execute query, even if there is normalized cache. I always though that ssrExchange will prevent client re-execution.
There's a short explanation here: https://formidable.com/open-source/urql/docs/advanced/persistence-and-uploads/#automatic-persisted-queries
tl;dr: Run this just as an SPA without SSR to see more clearly what's going on. You may have to check closely what the request looks like. Basically, this is because you're using automatic persisted queries. A second request will be sent when the hash that's sent is unknown to the server.
The longer explanation is in the docs ✌️
from urql.
Related Issues (20)
- useQuery in Nextjs Client Component should be executed from the client side HOT 3
- Passing a `Headers` object results in an error
- Possible memory leak when using multiple queries on the same page HOT 7
- requestPolicyExchange does not re-request in production HOT 3
- cacheExchange - cache.readQuery (updateQuery) can't find queries with aliased variables HOT 1
- @urql/exchange-persisted Module name, 'crypto' does not resolve to a valid URL. HOT 7
- Non RSC authExchange failing HOT 2
- Problem: @urql/exchange-graphcache updateCacheWithResult reads null after writing link in cache updater. HOT 8
- Invalidating cache in Graphcache doesn't trigger query refetch in Next.js app router HOT 2
- RFC: react native file upload support HOT 1
- Introspected schema from urql-introspection doesn't match type of exchange-graphcache HOT 1
- RFC: Graphcache strong typing HOT 3
- Graphcache: mutations with different files in parallel, results lost HOT 3
- Invalidate with a key does not produce expected result HOT 2
- RFC: Normalize embedded documents based on parent HOT 5
- Syntax Error: Unexpected token in SelectionSet HOT 1
- RFC: @urql/vue - Allow getter syntax in `useQuery` HOT 4
- RFC: Add secondary keys HOT 2
- @urql/exchange-graphcache returns empty data & error although fetch response contains valid data. (when same entity is requested in parallel) HOT 1
- Multiple requests when using react suspense HOT 13
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from urql.