Я пытаюсь настроить SSR для моего приложения React, которое использует клиент Apollo для запросов graphql к API. Я правильно настроил конфигурацию webpack и приложение Express, и я вижу, как загружаются компоненты. Проблема здесь в том, что getDataFromTree
вообще не ждет моего запроса. Он просто возвращает компонент с loading: true
, а затем ничего. Я также установил ssrForceFetchDelay
, чтобы клиент повторял запросы, но ничего.
Я продолжаю получать window.__APOLLO_STATE__={}
. Компоненты очень просты, делают простые запросы и отображают результат.
Это мое экспресс приложение:
app.use((req, res) => {
const client = new ApolloClient({
ssrMode: true,
link: new HttpLink({
uri: 'http://localhost:8000/graphql',
fetch: fetch
}),
cache: new InMemoryCache(),
});
const app = (
<ApolloProvider client={client}>
<Router location={req.url} context={{}}>
<App client={client}/>
</Router>
</ApolloProvider>
);
const jsx = extractor.collectChunks(app); // Using loadable
renderToStringWithData(jsx).then((dataResp) => {
const content = dataResp;
const state = client.extract(); // Always {}
const helmet = Helmet.renderStatic();
const html = ReactDOMServer.renderToStaticMarkup(
<Html content={content} helmet={helmet} assets={assets} state={state} />,
);
res.status(200); res.send(`<!doctype html>${html}`);
res.end();
}).catch(err => {
console.log(`Error thrown`);
});
});
app.listen(port, () => {
console.log(`Server listening on ${port} port`);
});
Это мой клиентский конфиг Apollo:
const cache = new InMemoryCache().restore(window.__APOLLO_STATE__);
const client = new ApolloClient({
ssrForceFetchDelay: 300,
link: links,
cache: cache,
connectToDevTools: true,
});
Мое приложение:
const Wrapped = () => {
console.log(`Inside Wrapped`);
return (
<ApolloProvider client={apolloClient}> //The client one
<Router>
<App /> /*Only returns 2 basic components */
</Router>
</ApolloProvider>
);
};
hydrate(<Wrapped />, document.getElementById('root'));
Я вижу компоненты на странице, но запросы не были загружены, а APOLLO_STATE всегда пуст. Я следовал документации по react-apollo
, чтобы настроить это, но я не могу понять, почему эта базовая установка не будет работать. Любые идеи о том, что мне нужно изменить здесь? Спасибо!
HTML-компонент:
import React from 'react';
const Html = ({ content, helmet, assets, state }) => {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="/manifest.json" />
<link rel="shortcut icon" href="/favicon.ico" />
{helmet.meta.toComponent()}
{helmet.title.toComponent()}
{assets.css &&
assets.css.map((c, idx) => (
<link key={idx} href={c} rel="stylesheet" />
))}
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root" dangerouslySetInnerHTML={{ __html: content }} />
<script
dangerouslySetInnerHTML={{
__html: `window.__APOLLO_STATE__=${JSON.stringify(state).replace(
/</g,
'\\u003c',
)};`,
}}
/>
{assets.js &&
assets.js.map((j, idx) => (
<script key={idx} src={j} />
))}
</body>
</html>
);
};
export default Html;
РЕДАКТИРОВАТЬ: добавлен мой HTML-код компонента
Ссылка на репо с базовым кодом, который работает правильно. Я намереваюсь добавить Loadable к этому, чтобы видеть, является ли это причиной проблемы.
https://github.com/kvnam/gql-ssr-test