-
-
Notifications
You must be signed in to change notification settings - Fork 349
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
Getting Stuck with Apollo #8
Comments
Hello Lydia, I'm glad it works now. Let me know if you have any questions. I'd gladly accept a PR adding an minimalistic Rom cc @chriscalo who has been curious about Apollo support. |
Hi @brillout, Thank you for such a quick response. I will do a PR if we move to Vite... which is looking likely! Since you offered, I do have two more questions... :) (I apologise for the lack of proper terminology, I don't really understand this stuff at all.) In our current next repo, we are using this package for apollo. As far as I understand it, it means you can just useQuery() everywhere, but it magically still works with ssr. Is this how apollo roughly works in your package:
Q2. I'm trying to get import module mapping working. I am perplexed because I was able to get this solution working in a git clone of the official vite starter repo for react-ts. However I cannot get it working in your starter and I believe I am doing the exact same thing! Is it at all possible that this is not possible for some reason in ssr? There is also no red line in the editor under the import... Apologies if this is another silly q, I've just been going round in circles about it :S src/components/Divvy.tsx
import React from 'react'
const Divvy = () => <div>hiii</div>
export default Divvy import React from "react";
import Divvy from '~/components/Divvy'
export { Page };
function Page({countries}) {
return (
<>
<Divvy />
<p className="bg-blue-200">A okay text.</p>
{countries.map(c => <div key={c.code}>{c.name}</div>)}
</>
);
}
Error: Failed to resolve import "
|
Correct.
While it would work, it's better if you don't do that: because otherwise you end up fetching your data twice which is wasteful (and can lead to hydration mismatch if the data changes in-between the two requests). Apollo's SSR doc looks good at first glance, check it out https://www.apollographql.com/docs/react/performance/server-side-rendering/. Note that instead of doing const client = new ApolloClient({
cache: new InMemoryCache().restore(JSON.parse(window.__APOLLO_STATE__)),
uri: 'https://example.com/graphql'
}); you can do // pages/tests/index.page.client.js
const client = new ApolloClient({
cache: new InMemoryCache().restore(pageProps.initialApolloState),
uri: 'https://example.com/graphql'
}); // pages/tests/index.page.server.js
import { html } from 'vite-plugin-ssr'
import { getDataFromTree } from "@apollo/client/react/ssr";
export { addContextProps }
export { setPageProps }
export { render }
// Note that `Page` is as well available to `addContextProps()`
async function addContextProps({ Page, contextProps }) {
let pageHtml;
let initialApolloState;
getDataFromTree(Page).then((_pageHtml) => {
pageHtml = _pageHtml
initialApolloState = client.extract();
});
return { pageHtml, initialApolloState }
}
async function render({ contextProps }) {
// Note how `pageHtml` is *not* computed in `render()` but provided by `addContextProps()`
const { pageHtml } = contextProps
return html`<!DOCTYPE html>
<html>
<body>
<div id="page-root">${html.dangerouslySetHtml(pageHtml)}</div>
</body>
</html>`
}
function setPageProps({ contextProps: { initialApolloState } }) {
// We pass `initialApolloState` to the browser
return { initialApolloState }
} About Q2, vite-plugin-ssr doesn't intefere with any of that. Very unlikely that the problem comes from vite-plugin-ssr. (But it may very well come from the fact that you are doing SSR and hence your code is being consumed by the browser as well as by Node.js.) |
Dear Romuald, I am so, so, so grateful for your help. Thank you. I apologise if this is taking too much of your time, please reply whenever you have time, if at all. I have tried to implement what you are saying but I have failed. I am getting In this part of your code, you are using a client... getDataFromTree(Page).then((_pageHtml) => {
pageHtml = _pageHtml
initialApolloState = client.extract();
}); As you are using // server/index.ts
import express from "express";
import { createPageRender } from "vite-plugin-ssr";
import * as vite from "vite";
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client'
import fetch from 'cross-fetch'
const isProduction = process.env.NODE_ENV === "production";
const root = `${__dirname}/..`;
startServer();
async function startServer() {
const app = express();
let viteDevServer;
if (isProduction) {
app.use(express.static(`${root}/dist/client`, { index: false }));
} else {
viteDevServer = await vite.createServer({
root,
server: { middlewareMode: true },
});
app.use(viteDevServer.middlewares);
}
const renderPage = createPageRender({ viteDevServer, isProduction, root });
app.get("*", async (req, res, next) => {
const client = new ApolloClient({
ssrMode: true,
link: createHttpLink({
uri: 'https://countries.trevorblades.com',
credentials: 'same-origin',
headers: {
cookie: req.header('Cookie'),
},
fetch
}),
cache: new InMemoryCache(),
})
const url = req.originalUrl;
const contextProps = { client };
const result = await renderPage({ url, contextProps });
if (result.nothingRendered) return next();
res.status(result.statusCode).send(result.renderResult);
});
const port = 3000;
app.listen(port);
console.log(`Server running at http://localhost:${port}`);
} I am confident that this client and query are working as this is working: //pages/tests/index.page.server.ts
async function addContextProps({ contextProps }) {
const response = await contextProps.client.query({query: LIST_COUNTRIES})
return { countries: response.data.countries }
} There are my other files... // pages/tests/index.page/server.ts
import { html } from 'vite-plugin-ssr'
import { getDataFromTree } from "@apollo/client/react/ssr";
export { addContextProps }
export { setPageProps }
export { render }
async function addContextProps({ Page, contextProps }) {
let pageHtml;
let initialApolloState;
getDataFromTree(Page).then((_pageHtml) => {
pageHtml = _pageHtml
initialApolloState = contextProps.client.extract(); // <- ssr: true client
});
return { pageHtml, initialApolloState }
}
async function render({ contextProps }) {
const { pageHtml } = contextProps
return html`<!DOCTYPE html>
<html>
<body>
<div id="page-root">${html.dangerouslySetHtml(pageHtml)}</div>
</body>
</html>`
}
function setPageProps({ contextProps: { initialApolloState } }) {
return { initialApolloState }
} These are my other files: //pages/tests2/index.page.server.ts
import { html } from 'vite-plugin-ssr'
import { getDataFromTree } from "@apollo/client/react/ssr";
export { addContextProps }
export { setPageProps }
export { render }
async function addContextProps({ Page, contextProps }) {
let pageHtml;
let initialApolloState;
getDataFromTree(Page).then((_pageHtml) => {
pageHtml = _pageHtml
initialApolloState = contextProps.client.extract();
});
return { pageHtml, initialApolloState }
}
async function render({ contextProps }) {
const { pageHtml } = contextProps
return html`<!DOCTYPE html>
<html>
<body>
<div id="page-root">${html.dangerouslySetHtml(pageHtml)}</div>
</body>
</html>`
}
function setPageProps({ contextProps: { initialApolloState } }) {
return { initialApolloState }
} //pages/tests2/index.page.client.ts
import {ApolloClient, InMemoryCache, ApolloProvider} from '@apollo/client'
import ReactDOM from "react-dom";
import React from "react";
import { getPage } from "vite-plugin-ssr/client";
hydrate();
async function hydrate() {
const { Page, pageProps } = await getPage();
const client = new ApolloClient({
cache: new InMemoryCache().restore(pageProps.initialApolloState),
uri: 'https://countries.trevorblades.com'
});
ReactDOM.hydrate(
<ApolloProvider client={client}><Page {...pageProps} /></ApolloProvider>,
document.getElementById("page-root")
);
} // pages/tests2/index.page.tsx
import { gql, useQuery } from '@apollo/client'
import React from "react";
export { Page };
export const LIST_COUNTRIES = gql`
{
countries {
name
code
}
}
`;
function Page() {
const {data} = useQuery(LIST_COUNTRIES)
console.log('data', data)
return (
<>
<p className="bg-blue-200">Tests2 </p>
</>
);
} |
Make sure to use await getDataFromTree(Page).then((_pageHtml) Otherwise Also you should initialize the Apollo client only once at startup time, instead of initializing it on every HTTP request. |
Thanks so much for your help with this, when we are up and running we will submit a PR :) |
So did it work? Looking foward to your PR. |
Well... no! But our best guess at the moment is that apollo's If you're interested... |
Hey, I got it working :) Will send a PR example tomorrow. Thanks so much for your help! |
Love it :-). Let me know if you need further help. |
@LydiaF did you figure out the import mapping issue you ran into? I'm encountering the same one. Any help would be incredibly appreciated. |
Hey @felixakiragreen, I deleted the last comment mistakenly if you read it, if you didnt: no good news from me. We couldn't fix it in the end and I had spent ages refactoring so I didn't get the circ dep warnings, but it still didn't work. I can't remember what exact the issue was but we figured it was probably the ssr circular dep issue in the vite repo and we decided, with heavy hearts, to let ssr go until it was fixed! |
Dear @brillout,
Thank you for this plugin, it looks very promising.
update: seems to be working perfectly now!
If you have time, would you mind creating a very basic example using apollo client? I am probably doing something stupid but I don't think I can figure it out on my own.
Thank you very much,
Lydia
The text was updated successfully, but these errors were encountered: