Last active
July 30, 2017 08:20
-
-
Save scazzy/0160c03d94602fa7684df55e7c82d040 to your computer and use it in GitHub Desktop.
SSR using React-transmit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* src/client.js | |
*/ | |
import React from 'react'; | |
import { render } from 'react-dom'; | |
import Transmit from 'react-transmit'; | |
import Root from './containers/Root' | |
window.onload = () => { | |
Transmit.render( | |
Root, | |
{ | |
locale: navigator.language, | |
browser: true | |
}, | |
document.getElementById('root') | |
) | |
} | |
/** | |
* Detect whether the server-side render has been discarded due to an invalid checksum. | |
*/ | |
if (process.env.NODE_ENV !== "production" || 1) { | |
const reactRoot = window.document.getElementById("root"); | |
if (!reactRoot || !reactRoot.firstChild || !reactRoot.firstChild.attributes || | |
!reactRoot.firstChild.attributes["data-react-checksum"]) { | |
console.error("Server-side React render was discarded. Make sure that your initial render does not contain any client-side code."); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* src/containers/Root.js | |
* App's root container | |
*/ | |
import React, { Component } from 'react'; | |
import { BrowserRouter, StaticRouter } from 'react-router-dom'; | |
import Redux from 'redux'; | |
import { Provider } from 'react-redux'; | |
import AppRoutes from '../routes/AppRoutes'; | |
import { IntlProvider, addLocaleData, defineMessages } from 'react-intl'; | |
import store from '../store'; | |
import * as intl from '../lang/intl'; | |
import * as browserHelper from '../helpers/browser'; | |
import Transmit from 'react-transmit'; | |
import axios from 'axios'; | |
import PropTypes from 'prop-types'; | |
/** | |
* Initialize i18n | |
* common for server and client | |
*/ | |
intl.init(); | |
const bootApiUrl = "http://dev-api.domain.com/api/v1/sg/boot"; | |
/** | |
* src/containers/Root.js | |
* App root view container | |
*/ | |
class Root extends Component { | |
constructor () { | |
super(); | |
this.defaultProps = { | |
bootdata: {} | |
} | |
} | |
componentDidMount () { | |
// Load Facebook SDK | |
// browserHelper.loadFBSDK(); | |
} | |
getChildContext() { | |
return { bootdata: this.props.bootdata } | |
} | |
render () { | |
const Router = this.props.browser === true ? BrowserRouter : StaticRouter; | |
const locale = this.props.locale.substring(0,2) || 'en'; | |
return ( | |
<Provider store={store}> | |
<IntlProvider locale={locale} messages={intl.getTranslations(locale)}> | |
<Router {...this.props}> | |
<AppRoutes /> | |
</Router> | |
</IntlProvider> | |
</Provider> | |
) | |
} | |
} | |
Root.childContextTypes = { | |
bootdata: PropTypes.object | |
}; | |
export default Transmit.createContainer(Root, { | |
initialVariables: {}, | |
fragments: { | |
bootdata () { | |
return axios.get(bootApiUrl).then(response => response.data.data); | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* src/server.js | |
*/ | |
import path from 'path'; | |
import express from 'express'; | |
import React from 'react'; | |
import Transmit from 'react-transmit'; | |
import { renderToString } from 'react-dom/server'; | |
import { StaticRouter } from 'react-router-dom'; | |
import cookieParser from 'cookie-parser'; | |
import boot from './boot'; | |
import Config from './config'; | |
import Root from './containers/Root'; | |
import * as intl from './lang/intl'; | |
import { readFile } from 'fs' | |
const app = new express(); | |
app.use(cookieParser()); | |
app.use('/assets', express.static('public/assets', { fallthrough: false })); | |
app.get('*.js', function (req, res, next) { | |
req.url = req.url + '.gz'; | |
res.set('Content-Encoding', 'gzip'); | |
next(); | |
}); | |
app.get('/*', (req, res) => { | |
const domain = req.get('host'); | |
const locale = req.cookies['locale'] || req.header('Accept-Language') || 'en'; | |
const context = {}; | |
if(!req.cookies['locale']) | |
res.cookie('locale', locale); | |
// TODO: | |
// Cache this part of rendering content of that page for every request | |
// | |
if (context.url) { | |
// Somewhere a `<Redirect>` was rendered | |
redirect(302, context.url); | |
} else { | |
// (<Root locale={locale} location={req.url} context={context} />) | |
// We're good, send the response | |
const indexFile = path.join(__dirname, '..', 'public','index.html') | |
const renderedHtml = Transmit.renderToString( | |
Root, | |
{ | |
locale, | |
location: req.url, | |
context | |
} | |
).then(({reactString, reactData}) => { | |
readFile(indexFile, 'utf8', (err, data) => { | |
if (err) throw err; | |
const document = data.replace('<!-- server -->', reactString); | |
res.send(document); | |
}) | |
}); | |
} | |
}); | |
app.listen(Config.port, (err) => { | |
if(err) { | |
return console.error(err); | |
} else { | |
console.log('Listening at :' + Config.port); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment