Repository URL to install this package:
|
Version:
1.2.11 ▾
|
@skava/react-server
/
src
/
serverSideRender
/
renderWithServerSide
/
classes
/
ServerSideRenderMaster.tsx
|
|---|
import Helmet from 'react-helmet'
import React from 'react'
import { renderToString } from 'react-dom/server'
// import { ServerStyleSheet } from 'view-container/styles/styled-components'
import { ServerStyleSheet } from '@skava/modules/___dist/view-container/styles/styled-components'
// import { ServerStyleSheet } from 'view-container'
import { StaticRouter } from 'react-router-dom'
import { getDataFromTree, ApolloProvider } from 'react-apollo'
import { Provider } from 'xmobx/mobx-react'
import { cacheIfNeeded } from '../../../middleware/cacheMiddleware'
import {
respondRedirect,
respondHyperText,
respondError,
} from '../../responders'
import { ServerHTML } from '../../HTML'
import { renderFinalString } from './renderFinalString'
import { ServerSideRenderContext } from './ServerSideRenderContext'
export class ServerSideRenderMaster {
private context: ServerSideRenderContext
constructor(context: ServerSideRenderContext) {
this.context = context
}
public onSuccess = () => {
const { req, res, reactRouterContext, htmlView } = this.context
cacheIfNeeded(req, res, htmlView)
/**
* Check if the router context contains a redirect, if so we need to set
* the specific status and redirect header and end the res.
*/
const { url, status } = reactRouterContext
if (url) {
respondRedirect(res, url)
} else {
respondHyperText(res, status, htmlView)
}
}
public onError = (apolloRenderingError: Error) => {
console.error('[EXCEPTION_ALERT] [ssr] APOLLO ERROR', apolloRenderingError)
respondError(this.context.res, apolloRenderingError)
}
public walk() {
return getDataFromTree(this.context.appView)
}
public setup() {
/**
* Create the job context for our provider,
* this grants us the ability to track the resolved jobs
* so we can send it back to the client.
*/
this.context.store = this.context.OmniStore.create()
}
public renderApp() {
const { req, reactRouterContext, store, client, App } = this.context
/**
* @description Declare our React application.
* @see https://www.apollographql.com/docs/react/recipes/server-side-rendering.html
*/
this.context.appView = (
<StaticRouter location={req.url} context={reactRouterContext}>
<ApolloProvider client={client}>
<Provider store={store}>
<App />
</Provider>
</ApolloProvider>
</StaticRouter>
)
}
/**
* @see https://github.com/styled-components/styled-components/issues/378
* @todo https://github.com/nfl/react-helmet/issues/216
* @see https://www.apollographql.com/docs/react/features/server-side-rendering.html#server-initialization
*/
public renderToString() {
const {
req,
appView,
nonce,
store,
reactRouterContext,
client,
} = this.context
const serializableExtractedApolloState = client.extract()
const sheet = new ServerStyleSheet()
const styledView = sheet.collectStyles(appView)
const appString = renderToString(styledView)
const styledTags = sheet.getStyleElement()
const htmlView = (
<ServerHTML
isCached={req.SHOULD_CACHE_SSR}
reactAppString={appString}
nonce={nonce}
helmet={Helmet.rewind()}
styledTags={styledTags}
apolloState={serializableExtractedApolloState}
storeState={store}
routerState={reactRouterContext}
/>
)
return renderFinalString(htmlView)
}
}