The "nearly invisible" way to server-render React applications
To make room for react-native-web support, we added a renderToString(app, ctx)
option so that you can have full control over how your app is rendered.
This can also be used to configure css-in-js
and so, ctx.markupRenderers
and the styled-components
and emotion
hocs are not necessary anymore, and have been deprecated.
Here's an example of using the renderToString
option to setup a css-in-js library:
const app = rogue(App, bundleUrl, {
renderToString(app, ctx) {
const markup = ReactDOM.renderToString(app)
const sheet = new ServerStyleSheet()
sheet.collectStyles(app)
ctx.app.headTags.push(sheet.getStyleTags())
return markup
}
})
SSR React application:
// server.js
import rogue from '@roguejs/app/server'
import App from './App'
const app = rouge(App, process.env.BUNDLE_URL)
// client.js
import hydrate from '@roguejs/app/client'
import App from './App'
hydrate(App)
React native web application (add the .native
suffix)
// server.js
import rogue from '@roguejs/app/server.native'
import App from './App'
const app = rouge(App, process.env.BUNDLE_URL)
// client.js
import hydrate from '@roguejs/app/client.native'
import App from './App'
hydrate(App)
note: if you use webpack, there's currently caching issues that cause problems with server-rendering if you import application logic from multiple bundles (https://github.com/alidcastano/rogue.js/issues/78), so for now we recommend you set it up programmatically. checkout the with-react-native example.
loadable-components
dependency since new version compatable with React 16.7 requires Webpack and Rogue is independent of any build setup (plus, React.lazy and Suspense makes it less necessary to have this built-in)@roguejs/cli
package. it was never finished (partly because we were waiting for Parcel to progress, partly due to time constraints) and there's already great ssr built tools like Razzle that solve this decently enoughOther than that, just simplified logic and added basic tests to app middleware. :)
bundleUrl
option (#68 #66 )Before:
const app = new Rogue(App, { bundleUrl })
Now:
const app = new Rogue(App, {
bodyTags: [`<script src="${bundleUrl}" defer></script>`]
})
A bit more code, but gives you more control over the tags added to your html document.
roguejs/app
:
listen
method to appFixes:
getInitialProps
for Routes #42 #6. It's primarily meant for querying data or redirecting, both of which are handled by Apollo Graphql and React Router, respectively. This change simplified codebase since we only have to walk component tree to App.js component.getInitialProp
methods. This fixes problem with initilizing hocs before App.js component. #47roguejs/app
code, we also refactored it to typescriptQuick glance at new API:
// App.js
export default () => 'Hello World!'
// client.js
import { hydrate } from '@roguejs/app'
import App from './App'
hydrate(App)
// server.js
import Rogue from '@roguejs/app/server'
import http from 'http'
import App from './App'
const app = new Rogue(App)
http.createServer(app.render).listen(3000)