Я пытаюсь преобразовать приложение express с отдельным интерфейсом реакции для использования рендеринга на стороне сервера.
У меня есть Apollo и Material-UI.
Сайт загружается правильно со стилями, но я не могу получить доступ ни к одному из сценариев реагирующих компонентов, которые необходимо загрузить после начальной загрузки. Где я ошибаюсь?
Мой express сервер:
const server = express();
const Html = ({
content,
state,
css
}: {
content: string;
state: any;
css: string;
}) => (
<html>
<head>
<style id="jss-server-side" dangerouslySetInnerHTML={{ __html: css }} />
</head>
<body>
<div id="root" dangerouslySetInnerHTML={{ __html: content }} />
<script
dangerouslySetInnerHTML={{
__html: `window.__APOLLO_STATE__=${JSON.stringify(state).replace(
/</g,
"\\u003c"
)};`
}}
/>
</body>
</html>
);
const schema = makeExecutableSchema({ typeDefs, resolvers });
addMockFunctionsToSchema({
schema,
preserveResolvers: true
});
server.use((req, res) => {
const sheets = new ServerStyleSheets();
const client = new ApolloClient({
ssrMode: true,
link: new SchemaLink({ schema }),
cache: new InMemoryCache()
});
const context = {};
getMarkupFromTree({
tree: sheets.collect(
<ApolloProvider client={client}>
<ThemeProvider theme={theme}>
<StaticRouter location={req.url} context={context}>
<Wrapper />
</StaticRouter>
</ThemeProvider>
</ApolloProvider>
),
renderFunction: renderToString
})
.then(markup => {
res.status(200);
const css = sheets.toString();
const state = client.extract();
const html = <Html content={markup} state={state} css={css} />;
res.send(`<!doctype html>\n${renderToString(html)}`);
res.end();
})
.catch(e => {
console.error("RENDERING ERROR:", e); // eslint-disable-line no-console
res.status(500);
res.end("");
});
});
server.listen({ port }, () =>
console.log(`Server ready at http://localhost:${port}`)
);
export default server;
Конфигурация Webpack:
export const clientConfig = {
entry: {
main: [
"webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000",
"./src/client/index.tsx"
]
},
output: {
path: path.join(__dirname, "./src/server/client/build"),
publicPath: "/",
filename: "index.js"
},
resolve: {
extensions: [".tsx", ".ts", ".js"]
},
mode: "development",
target: "web",
devtool: "#source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-react"],
plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]]
}
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader"
}
]
}
]
},
plugins: [new webpack.HotModuleReplacementPlugin()]
};
И я запускаю сервер в режиме разработки через dev-скрипт:
const compiler = webpack(clientConfig);
server.use(
webpackDevMiddleware(compiler, {
quiet: true,
noInfo: true,
publicPath: clientConfig.output.publicPath
})
);
server.use(
webpackHotMiddleware(compiler, {
log: false
})
);