1.1.0 • Published 7 years ago

react-router-redux-middleware v1.1.0

Weekly downloads
5
License
MIT
Repository
github
Last release
7 years ago

React Router Redux Middleware

Middleware for React + Router + Redux with Server Side Rendering.

Attention, this is an experimental project. It requires basic knowledge of involved frameworks.

Usage:

npm install react-router-redux-middleware --save-dev

We assume that you should already have express, webpack and webpack-dev-server. You will need them.

Server rendering basically takes your application, applies same Babel transformations as Webpack do, then renders it to a string. Because of that you will also need a babel-cli since it's the easiest way to run the server with Babel:

npm install babel-cli --save-dev

We assume that you either have .babelrc file or babel section in your package.json.

Alter your package.json and add to scripts section:

{
  "scripts": {
    "start": "NODE_ENV=development babel-node ./index.js",
    "server": "NODE_ENV=production babel-node ./index.js"
  }
}

Now it's time to configure your router.js:

import React from "react";
import {Router, Route} from "react-router";
import NotFound from './NotFound';

function def(promise) {
    return promise.then(cmp => cmp.default);
}

export default function(history) {

    return <Router history={history}>
        <Route path='/' getComponent={() => def(import('./App'))}/>
        <Route path='*' component={NotFound}/>
    </Router>;

}

And the way how you render your app, this hackery is especially required if you use async routes:

import React from "react";
import {render} from "react-dom";
import {Provider} from "react-redux";
import {browserHistory, match, Router} from "react-router";

import createRouter from "./router";
import createStore from "./reduxStore";

const mountNode = document.getElementById('app'); // !!!!! PLEASE NOTE ID OF MOUNT NODE !!!!!
const store = createStore(window.__PRELOADED_STATE__); // !!!!! PLEASE NOTE THE NAME OF VARIABLE !!!!!

function renderRoutes(routes, store, mountNode) {

    match({history: browserHistory, routes}, (error, redirectLocation, renderProps) => {

        render((
            <Provider store={store}>
                <Router {...renderProps} />
            </Provider>
        ), mountNode);

    });

}

renderRoutes(createRouter(browserHistory), store, mountNode);

Here is the sample index.html that should be a part of webpack build, e.g. emitted to you output path. It could be a real file or generated by HtmlWebpackPlugin, but it has to be known by Webpack.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>App</title>
<body>
<div id="app"></div><!-- !!!!! MUST EXACTLY MATCH THE SERVER CONFIG !!!!! -->
</body>
</html>

Now let's set up the server.js, you can add more customizations if needed:

import path from "path";
import Express from "express";
import webpack from "webpack";
import Server from "webpack-dev-server";
import createRouter from "./src/router"; // same file as in client side
import createStore from "./src/reduxStore"; // same file as in client side
import config from "./webpack.config";
import {createExpressMiddleware, createWebpackMiddleware, skipRequireExtensions} from "react-router-redux-middleware";

skipRequireExtensions(); // this may be omitted but then you need to manually teach Node to ignore non-js files

const port = process.env.PORT || 3000;

const options = {
    createRouter: createRouter,
    createStore: ({req, res}) => (createStore({
        foo: Date.now() // pre-populate something right here
    })),
    initialStateKey: '__PRELOADED_STATE__', // !!!!! MUST MATCH THE CLIENT
    template: ({template, html}) => (template.replace(
        // !!!!! MUST MATCH THE INDEX.HTML
        `<div id="app"></div>`,
        `<div id="app">${html}</div>`
    )),
    templatePath: path.join(config.output.path, 'index.html'),
    outputPath: config.output.path
};

if (process.env.NODE_ENV !== 'production') {

    const compiler = webpack(config);
    const middleware = createWebpackMiddleware(compiler, config);

    config.devServer.setup = function(app) {
        app.use(middleware(options));
    };

    new Server(compiler, config.devServer).listen(port, '0.0.0.0', listen);

} else {

    const app = Express();

    app.use(createExpressMiddleware(options));
    app.use(Express.static(config.output.path));

    app.listen(port, listen);

}

function listen(err) {
    if (err) throw err;
    console.log('Listening %s', port);
}
1.1.0

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago