Comments (14)
Thank you for your help.
I have issue with getDataFromTree
during the "hydration", this article helped me:
https://lihautan.com/hydrating-text-content/
So instead I use renderToStringWithData
.
from vite-ssr.
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 defaultTransformer
to the transformState
hook so you don't need to care about stringify/parse and escaping dangerous characters for XSS.
from vite-ssr.
Thank you for your help.
In the main.jsx, the state is always null.
I created a project it can be easier to test:
https://github.com/shenron/vite-ssr-plugin-react-demo
from vite-ssr.
@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 initialState: { apolloCache }
from your production server since it's already done in the main hook.
from vite-ssr.
@tcastelly I've added defaultTransformer
in 0.8.1
. You can simplify the transformState
like this (keep the code in the main hook as in the previous comment):
transformState(state, defaultTransformer) {
if (import.meta.env.SSR) {
state.apolloCache = state.apolloCache.extract();
}
return defaultTransformer(state);
}
from vite-ssr.
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.
I have "Loading ..." in my DOM and the cache is empty:
...
<script>window.__INITIAL_STATE__="{\"apolloCache\":{}}"</script>
...
I created an other project without the ssr plugin:
https://github.com/shenron/vite-ssr-react-demo/
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
from vite-ssr.
Ah I see, so the state now works but it cannot await for queries. vite-ssr
relies on Suspense viareact-ssr-prepass
. Looks like some updates in Apollo 3 have removed Suspense support so it's tricky to make it work:
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.
from vite-ssr.
@tcastelly I've been playing with Apollo internals for a while and I think I got it working. The simplest solution is probably using getDataFromTree
instead of React's renderToString
until Apollo supports Suspense. I'll try to figure out a way to provide it in vite-ssr
API soon π
from vite-ssr.
@tcastelly Can you check v0.9.0
? It should use renderToStringWithData
automatically if it detects you have @apollo/client
and @vitejs/plugin-react-refresh
installed.
I tried it in your repo and it does await for the loading
variable to become false
so it doesn't render Loading...
anymore. However, the GraphQL query returns undefined
for some reason but that might be related to the API π€
from vite-ssr.
It works better thank you :)
But I have a strange behavior.
In this demo project, each page resolve props once and the home page resolve a QraphQL query.
In the ./client/api.jsx
I print the state. In ssr mode I see only the apolloCache. Else I see the result of the default query.
// from ssr: { apolloCache: InMemoryCache2 }
// else {body: {β¦}}
console.log(route.meta.state);
return <Page {...route.meta.state} />;
To reproduce:
npm run dev
Go the the About page from Home. And try to load directly this About page.
Thank you very much for your help.
from vite-ssr.
@tcastelly I think that's expected π€ . Only the first route gets the initialState
in its route.meta.state
after rehydration. Further navigation (SPA mode) to other routes don't get anything in their respective route.meta.state
.
I'm not sure what you are trying to accomplish. If you need the whole initialState
in every page, you can pass it from your App.jsx as props I guess.
Also, are you going to mix Apollo queries and page-props?
from vite-ssr.
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
from vite-ssr.
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!
Thank you very much for your time.
Edit: Thank you for the new example with only react apollo
from vite-ssr.
@tcastelly Thanks for all the reproduction and information you provided here, glad it's now working!
from vite-ssr.
Related Issues (20)
- manualChunks errors in version 0.17.1 HOT 1
- Cannot read property 'ssrUtils' of undefined HOT 1
- Add support for streaming
- vueuse/head version
- δΈι’ζ―ζηζ₯ιδΏ‘ζ― δΉεθΏθ½η¨η°ε¨ε°±δΈθ‘δΊ HOT 6
- vite-ssr doesn't appear to be written in CJS, but also doesn't appear to be a valid ES module (i.e. it doesn't have "type": "module" or an .mjs extension for the entry point). Please contact the package author to fix. HOT 1
- vite-ssr build runs in development mode HOT 2
- vire-ssr has unmet peer dependency warnings
- Internal server error: render is not a function HOT 1
- Error isFunction is not a function from defineComponent called from ClientOnly component. HOT 2
- Unable to request data to set header title in hook function 'onServerPrefetch', page has already completed rendering before await HOT 1
- @vueuse/head 1.x versions Rendering problem
- What should I do if the client repeatedly renders after SSR?
- How to get request headers in Vercel HOT 1
- Bug: bad SSR index.html rendering. HOT 1
- Vue on client don't start lifecycle. HOT 1
- Failed to load url __vite-optional-peer-dep:@vueuse/head:vite-ssr HOT 1
- name export commafy not found
- Does this repo support code splitting?
- Vite 5 support HOT 3
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 vite-ssr.