tldr: demo here.

Now, we can combine all these libraries and tricks to create a serverless express webserver. This server uses redux-saga to pre-fetch all api calls that execute on the first render of your redux application, and pass the resulting data in the initial state that gets passed back to the client!

I created a small boilerplate for this behavior that I will explain briefly in this post. The boilerplate has two start-points; client.jsx and server.jsx.

The client.jsx is the script that takes the pre-rendered HTML and pre-filled state and starts your javascript application in the browser. You can deploy this client separately to a CDN to make for fast delivery times. In traditional applications, this would be the only script you have. You wait for it to download and then it would render your entire application. But not anymore!

Because now we also have server.jsx.

The server script takes care of rendering the application (just like client.jsx) but on the server. It will actually do two renders of your application. The first time it triggers all the redux-saga actions that fire on first render. Then it waits for these actions to finish and re-renders the app with the data that redux-saga fetched in the initial data object. The result of this render will be passed back to the client, ready for client.jsx to be used.

In my example boilerplate I have a movies-request that will fetch movies from a json file. In the container that displays these movies I call the moviesRequest in the constructor. As seen in this example:

// client/containers/Movies.jsx

constructor(props: Props) {

super(props); if (!props.movies.length) {

props.moviesRequest();

}

}

When the container is rendered, an action is fired that will be caught by redux-saga. The movies-saga will make a call for the json and fill the store with the movies. The next time this container is rendered, the movies will already be filled. That way it can render the movies without doing a new request. This is essentially how the server does the pre-rendering with data; it renders twice, first to start the actions and second to show the data.

// server/server.jsx

// When first render is done and all saga's are run, render again with updated store.

store.runSaga(rootSaga).done.then(() => {

const markup = renderToString(rootComp);

const html = renderHTML(markup, store); const result = context.getResult();

res.status(200).send(html);

}); // Do first render, starts initial actions.

renderToString(rootComp); // When the first render is finished, send the END action to redux-saga.

store.close();

You can read more about the Redux-Saga END action here.

You can see a demo here. (be sure to look at the page source)