This repository has been archived by the owner on Dec 2, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
renderer.tsx
79 lines (71 loc) · 2.68 KB
/
renderer.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { resolve } from 'path';
import { Request, Response } from 'express';
import React from 'react';
import { Provider } from 'react-redux';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import Helmet from 'react-helmet';
import { ServerStyleSheet } from 'styled-components';
import { ChunkExtractor } from '@loadable/server';
import { ApolloProvider, getMarkupFromTree } from 'react-apollo';
import { SchemaLink } from 'apollo-link-schema';
import { renderFullPage } from '../../renderFullPage';
import { Router } from '../../../client/router/index';
import { configureStore } from '../../../client/store/configureStore';
import { createClient } from '../../../graphql/client';
import { schema } from '../../../graphql/schema';
import { setBaseUrl } from '../../../client/actions/pages';
const statsFile = resolve(
__dirname,
process.env.NODE_ENV !== 'production'
? '../../../../dist/client/loadable-stats.json'
: '../../../../client/loadable-stats.json'
);
export async function get(req: Request, res: Response) {
const baseUrl = `${req.protocol}://${req.get('Host')}`;
const { nonce }: { nonce: string } = res.locals;
const { store, runSaga } = configureStore();
const client = createClient({ link: new SchemaLink({ schema }) });
const sheet = new ServerStyleSheet();
const context = {};
// for Node.js because `fetch` requires absolute URLs
store.dispatch(setBaseUrl(baseUrl));
const App = () => (
<ApolloProvider client={client}>
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
{/* add `div` because of `hydrate` */}
<div id="root">
<Router />
</div>
</StaticRouter>
</Provider>
</ApolloProvider>
);
try {
const extractor = new ChunkExtractor({ statsFile });
const tree = extractor.collectChunks(<App />);
await Promise.all([
// kick apollo, redux-saga, and styled-components
getMarkupFromTree({
tree,
renderFunction: renderToStaticMarkup,
}),
runSaga(),
]);
const body = renderToString(tree);
const preloadedState = JSON.stringify(store.getState());
const helmetContent = Helmet.renderStatic();
const meta = `
${helmetContent.meta.toString()}
${helmetContent.title.toString()}
`.trim();
const style = sheet.getStyleTags();
const scripts = extractor.getScriptTags({ nonce });
const graphql = JSON.stringify(client.extract());
return res.send(renderFullPage({ meta, body, style, preloadedState, scripts, graphql, nonce }));
} catch (e) {
console.error(e);
return res.status(500).send(e.message);
}
}