static async getInitialProps({ renderPage }) { const sheet = new ServerStyleSheet(); const page = renderPage(App => props => sheet.collectStyles(<App {...props} />) ); const styleTags = sheet.getStyleElement(); // see https://github.com/nfl/react-helmet#server-usage for more information // 'head' was occupied by 'renderPage().head', we cannot use it return { ...page, styleTags, helmet: Helmet.rewind() }; }
export default function renderHtmlPage(store, html = '') { const head = Helmet.rewind(); const assets = global.webpackIsomorphicTools.assets(); let page = `<!DOCTYPE html><html ${head.htmlAttributes.toString()}>`; page += '<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">'; page += '<meta http-equiv="X-UA-Compatible" content="IE=edge"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">'; page += head.base.toString() + head.title.toString() + head.meta.toString() + head.link.toString(); page += Object.keys(assets.styles).map(style => `<link href="${assets.styles[style]}" rel="stylesheet" type="text/css">` ).join(''); page += `</head><body><div id="app"><div>${html}</div></div>`; if (store) { page += `<script type="text/javascript">window.__INITIAL_STATE__=${serialize(store.getState())}</script>`; } page += Object.keys(assets.javascript).reverse().map(script => `<script src="${assets.javascript[script]}"></script>` ).join(''); page += head.script.toString(); page += '</body></html>'; return page; }
app.use( ( req, res ) => { const reduxStore = configureStore( ); const sheet = new ServerStyleSheet(); reduxStore.dispatch( { type: "SERVER_READY" } ); // will be replaced later with a init session prefetchData( req.url, reduxStore.dispatch ).then( ( ) => { const head = Helmet.rewind( ); const reduxState = reduxStore.getState( ); const context = { }; const jsx = ( <ReduxProvider store={ reduxStore }> <StaticRouter location={ req.url } context={ context } > <App /> </StaticRouter> </ReduxProvider> ); const reactDom = renderToString( sheet.collectStyles( jsx ) ); const styles = sheet.getStyleTags(); res.writeHead( 200, { "Content-Type": "text/html" } ); res.end( templateHtml( head, reactDom, reduxState, styles ) ); } ).catch( err => console.log( err ) ); } );
render() { const { component, store } = this.props const head = Helmet.rewind() const htmlAttributes = head.htmlAttributes.toComponent() return ( <html lang={htmlAttributes.lang}> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="shortcut icon" href="/favicon.ico" /> {head.title.toComponent()} {head.meta.toComponent()} {head.link.toComponent()} {head.script.toComponent()} {this.styles} </head> <body> <div id="root" dangerouslySetInnerHTML={{ __html: renderToString(component) }} /> <script dangerouslySetInnerHTML={{ __html: `window.__PRELOADED_STATE__=${serialize(store.getState())};` }} /> {this.scripts} </body> </html> ) }
const head = Helmet.rewind();
/** * Performs server-side rendering. The function is exported because the templating function * that Spring will call uses this function to perform the meat of the rendering. * * @param path the path to the resource requested by the client * @param state the Redux state supplied by Spring and massaged by the template engine * @returns string the rendered page */ // eslint-disable-next-line import/prefer-default-export export function renderApp(path : string, state : Object) { const store = createStore(state); // 404's will be handled by correct route definitions. Redirects will be handled by Spring. const markup = renderToString( <Provider store={ store }> <StaticRouter location={ path } context={ {} } > <App/> </StaticRouter> </Provider> ) // Free accumulated object to avoid memory leak and return data to parent renderer const head = Helmet.rewind(); return { markup, head }; }
const Html = ({ assets, component, store }) => { const content = component ? ReactDOMServer.renderToString(component) : ''; const head = Helmet.rewind(); // magic.gif
</Provider> ); const head = Helmet.rewind();
let head = Helmet.rewind();
const head = Helmet.rewind() const initialState = JSON.stringify(store.getState())
render() { const { component, assetPath, store, type, location } = this.props const content = component ? ReactDOM.renderToString(component) : '' const state = JSON.stringify(store.getState()) const head = Helmet.rewind() return ( <html> <head> { head.title.toComponent() } { head.meta.toComponent() } <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link href="https://fonts.googleapis.com/css?family=Josefin+Sans:400,400i,600,600i|Lora:700,700i" rel="stylesheet" /> <script dangerouslySetInnerHTML={{ __html: `window.store=${state};` }} charSet="UTF-8" /> </head> <body> <Style rules={ styles } /> <div id="root" dangerouslySetInnerHTML={{ __html: content }} /> <script src="/assets/js/tinymce/tinymce.min.js" /> <script src={`/assets/${type}/bundle.js`} charSet="UTF-8" /> </body> </html> ) }
render () { const {component, store, data} = this.props; const content = component ? ReactDOM.renderToString(component) : ''; const head = Helmet.rewind(); return ( <html lang='en-us'> <head> {head.base.toComponent()} {head.title.toComponent()} {head.meta.toComponent()} {head.link.toComponent()} {head.script.toComponent()} <link rel='shortcut icon' href='/favicon.ico' /> <meta name='viewport' content='width=device-width, initial-scale=1' /> <style type='text/css'>{data.css.join('')}</style> </head> <body> <div id='content' dangerouslySetInnerHTML={{__html: content}} /> <script dangerouslySetInnerHTML={{__html: `window.__data=${serialize(store.getState())};`}} charSet='UTF-8' /> <script src='http://localhost:9001/dist/bundle.js' /> </body> </html> ); }
render() { const {assets, component, store} = this.props const content = component ? ReactDOM.renderToString(component) : '' const head = Helmet.rewind() return ( <html lang="en-us">
const head = Helmet.rewind();
const head = Helmet.rewind();