-
Notifications
You must be signed in to change notification settings - Fork 91
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
Extract Apollo cache for SSR #22
Comments
Hi @tcastelly ! Tell me if something like this works in your project: // This is the server renderer we just built
const main = import('../dist/server/main.js');
server.get('*', async (req, res) => {
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
const renderPage = (await main).default.default;
const apolloCache = new InMemoryCache();
const { html } = await renderPage(url, {
manifest,
- apolloCache,
+ initialState: { apolloCache },
preload: true,
});
res.setHeader('Cache-Control', 'max-age=0');
res.end(html);
}); const App = ({
isClient,
- apolloCache = new InMemoryCache(),
+ initialState,
}) => {
const client = new ApolloClient({
link: createHttpLink({
uri: 'http://localhost:8080/graph',
credentials: 'same-origin',
}),
ssrMode: !isClient,
- cache: apolloCache,
+ cache: initialState.apolloCache,
credentials: 'same-origin',
}); export default viteSSR(App, {
routes,
transformState(state) {
if (import.meta.env.SSR) {
// Serialize
state.apolloCache = state.apolloCache.extract()
return JSON.stringify(JSON.stringify(state))
} else {
// Deserialize
state = JSON.parse(state)
state.apolloCache = new InMemoryCache().restore(JSON.parse(state.apolloCache))
return state
}
}
}, (ctx) => {
// Custom initialization hook
}) If this works, I will add a second parameter |
Thank you for your help. In the main.jsx, the state is always null. |
@tcastelly Ah right, I forgot about the development server. This fixes it and is a bit simpler: export default viteSSR(App, {
routes,
transformState(state) {
if (import.meta.env.SSR) {
// Serialize
state.apolloCache = state.apolloCache.extract();
return JSON.stringify(JSON.stringify(state));
}
// Deserialize
return JSON.parse(state);
},
}, ({ initialState }) => {
// Custom initialization hook
if (import.meta.env.SSR) {
initialState.apolloCache = new InMemoryCache();
} else {
initialState.apolloCache = new InMemoryCache().restore(initialState.apolloCache);
}
}); You can stop passing |
@tcastelly I've added transformState(state, defaultTransformer) {
if (import.meta.env.SSR) {
state.apolloCache = state.apolloCache.extract();
}
return defaultTransformer(state);
} |
Thank you for your help. I updated the plugin and files like this: ./back/index.mjs const { html } = await renderPage(url, {
manifest,
initialState: { },
preload: true,
}); ./client/main.jsx export default viteSSR(App, {
routes,
transformState(state, defaultTransformer) {
if (import.meta.env.SSR) {
state.apolloCache = state.apolloCache.extract();
}
return defaultTransformer(state);
},
}, ({ initialState }) => {
// Custom initialization hook
if (import.meta.env.SSR) {
initialState.apolloCache = new InMemoryCache();
} else {
initialState.apolloCache = new InMemoryCache().restore(initialState.apolloCache);
}
}); Maybe I missed something, but The behavior is the same. The SSR does not wait the end of the Graphql query. ...
<script>window.__INITIAL_STATE__="{\"apolloCache\":{}}"</script>
... I created an other project without the ssr plugin: The only way that I found to fix my issue is to use: import { getDataFromTree } from '@apollo/client/react/ssr'; https://github.com/shenron/vite-ssr-react-demo/blob/es6/src/entry-server.jsx#L22 |
Ah I see, so the state now works but it cannot await for queries.
I wasn't aware that Apollo is not compatible with Suspense. I'll have a deeper look at it later this week and see if there's anything that we can do here. |
@tcastelly I've been playing with Apollo internals for a while and I think I got it working. The simplest solution is probably using |
Thank you for your help. I have issue with So instead I use |
@tcastelly Can you check I tried it in your repo and it does await for the |
It works better thank you :) In this demo project, each page resolve props once and the home page resolve a QraphQL query. In the // from ssr: { apolloCache: InMemoryCache2 }
// else {body: {…}}
console.log(route.meta.state);
return <Page {...route.meta.state} />; To reproduce:
Go the the About page from Home. And try to load directly this About page. Thank you very much for your help. |
@tcastelly I think that's expected 🤔 . Only the first route gets the I'm not sure what you are trying to accomplish. If you need the whole Also, are you going to mix Apollo queries and page-props? |
I've added a simple example for manual testing based on your repo here: https://github.com/frandiox/vite-ssr/tree/master/examples/react-apollo |
I'm agree, only the first route gets the initialState. I created this project from your react example and I added an Apollo Query to try. So I mixed Apollo queries and page props. Maybe not a good idea because there is no more props in pages during the first launch. Anyway, vite-ssr plugin with Apollo works now! Edit: Thank you for the new example with only react apollo |
@tcastelly Thanks for all the reproduction and information you provided here, glad it's now working! |
Hello,
I'm trying to use Apollo Client with SSR and React.
My idea was to create a
InMemoryCache
and extract data from the store. It seams thatviteSSR
does not wait the resolution of a query. If I add asetTimeout
to the hook ofviteSSR
, I cant print the good content of the store.According the Apollo Documentation, I have to use
renderToStringWithData
. But I have no idea how I can manage with vite-ssr plugin. Is it possible?Thank you very much.
./server/index.js
./src/App.jsx
./src/main.jsx
The text was updated successfully, but these errors were encountered: