mhaagens / react-mobx-react-router4-boilerplate

React, React-Router 4, MobX and Webpack 2-boilerplate with async routes.
560 stars 137 forks source link

Server Side Rendering #14

Closed akusany2 closed 7 years ago

akusany2 commented 7 years ago

How would you achieve SSR through this approach, as there is no common routes file and using miss/match on routes? I'm confused

mhaagens commented 7 years ago

This repo doesn't support SSR yet as there's some added complexity when it comes to code splitting etc. I am working on a branch for SSR, but it's not quite there yet, but here's an example of what the server side would look like using React Router 4's <ServerRouter />;

import webpack from 'webpack'
import express from 'express'
import devMiddleware from 'webpack-dev-middleware'
import hotMiddleware from 'webpack-hot-middleware'
import config from '../webpack.config.babel'
import React from 'react'
import { Provider } from 'mobx-react'
import { renderToString } from 'react-dom/server'
import { ServerRouter, createServerRenderContext } from 'react-router'

import App from '../common/components/App'
import CounterStore from '../common/stores/CounterStore'

const server = express()

if (process.NODE_ENV !== 'production') {
    const compiler = webpack(config)

    server.use(devMiddleware(compiler, {
        publicPath: config.output.publicPath,
        historyApiFallback: true,
    }))

    server.use(hotMiddleware(compiler))
}

server.get('*', (req, res) => {
    const context = createServerRenderContext()

    const counterStore = new CounterStore()
    const stores = {
        counterStore: counterStore
    }
    const initialState = { 
        counterStore: counterStore.toJson()
    }

    let markup = renderToString(
        <ServerRouter 
            location={req.url}
            context={context}>
            <Provider {...stores}>
              <App />
            </Provider>
        </ServerRouter>
    )

    const result = context.getResult()

    if (result.redirect) {
        res.writeHead(301, {
            Location: result.redirect.pathname
        })
        res.end()
    } else {

        if (result.missed) {
            res.writeHead(404)
            markup = renderToString(
                <ServerRouter
                    location={req.url}
                    context={context}>
                    <Provider {...stores}>
                      <App />
                    </Provider>
                </ServerRouter>
            )
        }

        let html = `<!doctype html>
        <html>
          <head>
            <title>Sample App</title>
            <script>
                window.__INITIAL_STATE__ = ${ JSON.stringify(initialState) };
            </script>
            <meta name="viewport" content="width=device-width, initial-scale=1">
          </head>
          <body>
            <div id='root'>${markup}</div>
            <script src="/static/bundle.js"></script>
          </body>
        </html>`

        res.write(html)
        res.end()
    }
})

server.listen(3000, (err) => {
    if (err) {
        return console.error(err)
    }
    console.log('Listening at http://localhost:3000/')
})