T
TanStack•8mo ago
evident-indigo

dehydrate / rehydrate apollo cache

looking to fetch a query inside my loader function and then write the apollo cache to a global variable. of course, i'd rather use tanstack query in the router but i'm working on mgirating a legacy project over from nextjs. is there a way to inject a variabe into the html on the serverside? it should be easy enough to read from window.APOLLO_STATE on the client side, but i'm unsure how to write it to the page with the data from my loaders https://www.apollographql.com/docs/react/performance/server-side-rendering
Apollo GraphQL Docs
Server-side rendering
45 Replies
dependent-tan
dependent-tan•8mo ago
the Apollo TanStack start integration is currently being developed
evident-indigo
evident-indigoOP•8mo ago
is there a link to that anywhere? a hacky workaround i can use for now?
dependent-tan
dependent-tan•8mo ago
cc @Lenz Weber-Tronic
xenophobic-harlequin
xenophobic-harlequin•8mo ago
https://github.com/apollographql/apollo-client-nextjs/pull/419#issuecomment-2609678429 with README https://github.com/apollographql/apollo-client-nextjs/blob/next/packages/tanstack-start/README.md But there was just a PR merged in TSR that might break some things. Give it a week. As a hacky workaround stay on exactly these versions with exactly these patches applied, together with the linked library: https://github.com/apollographql/apollo-client-nextjs/blob/1306572238ff9d9421b16164fc039d5b61f17ce9/package.json#L33-L34
xenophobic-harlequin
xenophobic-harlequin•8mo ago
going to try setting this up now - will report back is @apollo/client-integration-tanstack-start a standalone package?
xenophobic-harlequin
xenophobic-harlequin•8mo ago
No description
xenophobic-harlequin
xenophobic-harlequin•8mo ago
or do i just need @apollo/client at 3.12.6 @Lenz Weber-Tronic running into some issues downloading the patched dependencies, might be missing something stupid though does this add an apollo provider internally? pretty cool set up, seems really flex if it's all hydrated and available through router context
xenophobic-harlequin
xenophobic-harlequin•8mo ago
Yeah seeems the build is broken somehow.. should be available at https://pkg.pr.new/apollographql/apollo-client-nextjs/@apollo/client-integration-tanstack-start@419 but is not right now. I'll take a look a bit later And yeah, that does all the setup of the provider etc for you.
xenophobic-harlequin
xenophobic-harlequin•8mo ago
beautiful - can you let me know when the build is working @Lenz Weber-Tronic ? happy to set it up and provide feedback
xenophobic-harlequin
xenophobic-harlequin•8mo ago
@tyler I won't get to fixing the build on that branch right now, but I looked around, and this one should do the trick for now:
npm i https://pkg.pr.new/apollographql/apollo-client-nextjs/@apollo/client-integration-react-router@412
npm i https://pkg.pr.new/apollographql/apollo-client-nextjs/@apollo/client-integration-react-router@412
xenophobic-harlequin
xenophobic-harlequin•8mo ago
@tyler this PR is now compatible with TSR 1.99: https://github.com/apollographql/apollo-client-nextjs/pull/422 You can install it like this:
npm i https://pkg.pr.new/apollographql/apollo-client-nextjs/@apollo/client-integration-tanstack-start@422
npm i https://pkg.pr.new/apollographql/apollo-client-nextjs/@apollo/client-integration-tanstack-start@422
xenophobic-harlequin
xenophobic-harlequin•8mo ago
beautiful i'll try it out today @Lenz Weber-Tronic setting this up now - is there a way to access the apolloClient from a serverFn
xenophobic-harlequin
xenophobic-harlequin•8mo ago
I'm not sure if those exist within or independently of the router - if they exist within, you should be able to access it on the router context
xenophobic-harlequin
xenophobic-harlequin•8mo ago
is this the error you mentioned? Error in renderToPipeableStream: Error: useTransportValue must be used within a streaming-specific ApolloProvider "@tanstack/react-router": "^1.98.3", "@tanstack/start": "^1.98.3", @Lenz Weber-Tronic do i need downgrade to the patched dependencies up there?
xenophobic-harlequin
xenophobic-harlequin•8mo ago
No, upgrade. You need 1.99.4 at lat 1.99 completely changed the streaming so I had to rewrite a lot, it won't work with older versions now (npm should also tell you) but as a result you don't need to patch anything
xenophobic-harlequin
xenophobic-harlequin•8mo ago
got it - trying again now seems to be working !
rival-black
rival-black•8mo ago
Can I hijack here and ask if any of yall here have hit this?
8:21:35 PM [vite] (ssr) Error when evaluating SSR module $vinxi/handler/ssr: Missing "./index.js" specifier in "@apollo/client-integration-tanstack-start" package
Plugin: vite:import-analysis
File: <snip>/src/api/client/createClient.ts:2:29
1 | import { ApolloLink, fromPromise, split } from "@apollo/client";
2 | import { ApolloClient } from "@apollo/client-integration-tanstack-start";
| ^
8:21:35 PM [vite] (ssr) Error when evaluating SSR module $vinxi/handler/ssr: Missing "./index.js" specifier in "@apollo/client-integration-tanstack-start" package
Plugin: vite:import-analysis
File: <snip>/src/api/client/createClient.ts:2:29
1 | import { ApolloLink, fromPromise, split } from "@apollo/client";
2 | import { ApolloClient } from "@apollo/client-integration-tanstack-start";
| ^
EDIT: Ugh sorry. It was a bad regex on my side trying to fix @apollo/client importing CJS.
vite: {
resolve: {
alias: [
{
find: /^(@apollo\/client(?=\/|$)[^.]*)$/,
replacement: '$1/index.js',
},
vite: {
resolve: {
alias: [
{
find: /^(@apollo\/client(?=\/|$)[^.]*)$/,
replacement: '$1/index.js',
},
xenophobic-harlequin
xenophobic-harlequin•7mo ago
Also sharing that here - first alpha has shipped: https://www.npmjs.com/package/@apollo/client-integration-tanstack-start
npm
@apollo/client-integration-tanstack-start
This package provides integrations between Apollo Client and TanStack Start to support modern streaming SSR.. Latest version: 0.12.0-alpha.0, last published: 19 hours ago. Start using @apollo/client-integration-tanstack-start in your project by running npm i @apollo/client-integration-tanstack-start. There are no other projects in the npm regi...
rival-black
rival-black•7mo ago
Huge amount of work @Lenz Weber-Tronic thank you.
evident-indigo
evident-indigoOP•7mo ago
hey @Lenz Weber-Tronic , apologies if this is the wrong place for this. is there a way to prefetch a query in the route loader and still read it using useSuspenseQuery in the component, and ensure that if it's cahced (via the prefetch) it won't trigger another fetch in the child the example in the docs don't mention doing this, but i'd like to be able to prefetch a query in my route loader, and then read it in the component without having to pass props or read from useLoaderData in the child component.
No description
xenophobic-harlequin
xenophobic-harlequin•7mo ago
It should work, but it's more "loose" and i might depend on timing circumstances if a second network request happens or not. I'd go either way - only in the component (which will also prevent a request in the browser, just like the loader) or in the loader with useReadQuery. You might also want to just look into useSuspenseFragment, which shipped today with Apollo Client 3.13.
evident-indigo
evident-indigoOP•7mo ago
if i use a regular useQuery + fetchPolicy: cache-first will that also read from the hydrated apollo cache if i fetch inside a loader? @Lenz Weber-Tronic
xenophobic-harlequin
xenophobic-harlequin•7mo ago
Yes, but it wouldn't SSR, as non-suspenseful hooks cannot "pause" a render in SSR and wait for the data to come in to render it. I would generally recommend sticking to suspenseful hooks.
evident-indigo
evident-indigoOP•7mo ago
yeah we just have some old code that may be annoying to migrate
xenophobic-harlequin
xenophobic-harlequin•7mo ago
If you're okay with a loading state during SSR that should work
evident-indigo
evident-indigoOP•7mo ago
i'm not entirely sure the difference, if i streamed using the suspenseful hook, wouldn't it also render the suspense fallback during ssr? or is there a chance it could have the data even if we don't await it in the loader
xenophobic-harlequin
xenophobic-harlequin•7mo ago
It will stream the suspense fallback, but then also the rendered component. That's the magic of streaming SSR. Without suspense it only streams "loading" and then renders content in the client. The true magic is in the case of a search enging - it doesn't stream the suspense fallback, but waits for content
evident-indigo
evident-indigoOP•7mo ago
don't you still need client side JS to update the DOM if the initial HTML response comes down before the suspensed data is ready
xenophobic-harlequin
xenophobic-harlequin•7mo ago
yes, but that streams as part of the HTML in script tags, it can already render that stuff in before the potentially very big .js files are parsed and executed
evident-indigo
evident-indigoOP•7mo ago
i was thinking that. so it is brilliant. and it just renders the suspense fallback if the user has JS disabled?
xenophobic-harlequin
xenophobic-harlequin•7mo ago
yap unless they're a search engine, then it just takes longer until the final content comes in
evident-indigo
evident-indigoOP•7mo ago
react does that automatically?
xenophobic-harlequin
xenophobic-harlequin•7mo ago
rival-black
rival-black•7mo ago
This stuff is magic ✨
dependent-tan
dependent-tan•7mo ago
mostly "black magic" TBH 😄
rival-black
rival-black•7mo ago
Based on the src I've scrolled through in both of these repos that is 💯 😆 @Lenz Weber-Tronic is .toPromise() going away? how can I wait for the GQL data before rendering SSR? Or am I thinking about this wrong?
xenophobic-harlequin
xenophobic-harlequin•7mo ago
Unfortunately, functions are not serializable and you are passing that object over the wire, so unless you are using it client-side only without SSR, it's going away. That said, I can't think of a really good use for it, given that you can just suspend a full page.
rival-black
rival-black•7mo ago
Ok that helps. Struggling here learning both TanStack (router & start) & suspense at the same time lol
xenophobic-harlequin
xenophobic-harlequin•7mo ago
@Lenz Weber-Tronic we're getting this error when passing in preload query ref created in the loader Error in renderToPipeableStream: Invariant Violation: Expected a QueryRef object, but got something else instead. worth noting that it works on the client, but this error is logged on the server
evident-indigo
evident-indigoOP•7mo ago
i imagine we have some mismatch in our node_modules or it's trying to compare the symbol from an ESM build and an identical CJS build and that's why the equality check fails.
xenophobic-harlequin
xenophobic-harlequin•7mo ago
Yeah, I'm aware that this can happen - I'm currently on a very big ticket, but once I'm done with that I'll look into this @tyler @matthewsomethin could you update Apollo Client to 3.13.2 which was just released and see if that fixes the problem?
evident-indigo
evident-indigoOP•7mo ago
let me try. we just updated to 3.13.1 a few hours ago haha that didn’t work @Lenz Weber-Tronic
xenophobic-harlequin
xenophobic-harlequin•6mo ago
Dang :/ Could you provide me with a reproduction of this? I just released a new version of the support package, could you report back if that improves anything? 🙂
evident-indigo
evident-indigoOP•6mo ago
of the tanstack client?
xenophobic-harlequin
xenophobic-harlequin•6mo ago
@apollo/client-integration-tanstack-start@0.12.0-alpha.3 - no direct changes in that one, but some changes in the core it relies on (@apollo/client-react-streaming@0.12.0-alpha.3) that might be relevant for this problem

Did you find this page helpful?