-
-
Notifications
You must be signed in to change notification settings - Fork 444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ExecuteExchange doesn't interact well with "server-only" code #3587
Comments
Hey, I wouldn't say this is up to us specifically, the issue here are the limitations being quite... hard to work around.
What would circumvent your issue here is not importing from an urql package that depends on React so your server-provider becomes: import 'server-only'
import {executeExchange} from "@urql/exchange-execute";
import {type Client, type SSRExchange, type Exchange} from "@urql/core";
import {cacheExchange, createClient, ssrExchange} from "@urql/core";
|
Describe the bug
Hi,
I'm trying to use the execute exchange in a NextJS project. I've struggled with this over the last week (and posted a Q&A here with what I thought was a solution), but now I think this is a situation not fully considered by URQL.
The problem is I want to initialise the URQL execute exchange with my executable schema in a module marked
"server-only"
to ensure this code is not bundled into the client bundle. Note: the"server-only"
directive comes from the packageyarn add server-only
.The client factory is defined in
src/lib/server.ts
:Note: the
createURQLClientForServer
may or may not need to beasync
, but it was from earlier attempts to solve this issue using the commented out dynamic import which returns a Promise.There is also a corresponding factory function to create the URQL client in the browser environment, in
src/lib/client.ts
:So the problem is how to use these then to initialise the
UrqlProvider
in the layout.The fact
createURQLClientForServer
is marked server-only and is async leads me to think I should create a server-component to wrap the provider. So insrc/contexts/graphql/provider-server.ts
, I have:Using an
async
server component allowscreateURQLClientForServer
to be awaited and avoid conditional rendering, which ultimately makes SSR pointless unless you use streaming SSR on all of your pages (since the SSR would just show a loading state on all of your pages).There's an analogous provider in
src/contexts/graphql/provider-client.ts
Then to put it all together, we need to conditionally render either the server or client provider. This is done in
src/contexts/graphql/provider.ts
:Unfortunately, this throws a compilation error:
Call stack
Note: this error goes away if you mark
src/contexts/graphql/provider.ts
as "use client", but then you are forced to remove the "server-only" fromsrc/lib/server.ts
. With this the application functions as expected, SSR is performed with the execute exchange allowing GraphQL queries in my pages to be resolved in-memory, while CSR works via the fetchExchange. However, I don't think this should be relied upon.I've tried several implementations of
GraphqlProvider
, but they all have the same problems, e.g. using a function to get the provider rather than wrapping it with a new component:So, it seems that supporting "server-only" code is very difficult to achieve for reasons in both NextJS and the execute exchange. I'm not sure if this situation has been fully considered in the NextJS integration.
Reproduction
https://github.com/gregbrowndev/todo-app
Urql version
urql 4.0.7
Validations
The text was updated successfully, but these errors were encountered: