Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Server-side Rendering (SSR) for ReactJS / Flux Applications. Setting document.title


The basic structure of a React+Flux application (see other examples)

 - /src/actions/AppActions.js     - Action creators (Flux)
 - /src/components/Application.js - The top-level React component
 - /src/constants/ActionTypes.js  - Action types (Flux)
 - /src/core/Dispatcher.js        - Dispatcher (Flux)
 - /src/stores/AppStore.js        - The main store (Flux)
 - /src/app.js                    - Client-side startup script
 - /src/server.js                 - Server-side startup script

The Top-level React Component

// src/components/Application.js

var React = require('react');

var Application = React.createClass({

  propTypes: {
    path: React.PropTypes.string.isRequired,
    onSetTitle: React.PropTypes.func.isRequired

  render() {
    var page = AppStore.getPage(this.props.path);
    return (
      <div className="container">

module.exports = Application;

Client-side Startup Script (aka Bootstrap)

// src/app.js

var React = require('react');
var Dispatcher = require('./core/Dispatcher');
var Application = require('./components/Application');

var app = React.createElement(Application, {
  path: window.location.pathname,
  onSetTitle: (title) => document.title = title

app = React.render(app, document.body);

Dispatcher.register((payload) => {
  if (payload.action.actionType === ActionTypes.CHANGE_LOCATION) {
    app.setProps({path: payload.action.path});

Server-side Startup Script (Node.js/Express)

// src/server.js

var _ = require('lodash');
var express = require('express');
var React = require('react');

// The top-level React component + HTML template for it
var Application = React.createFactory(require('./components/Application'));
var template = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8');

var server = express();

server.set('port', (process.env.PORT || 5000));

// Server-side rendering (SSR)
server.get('*', function(req, res) {
  var data = {};
  var component = Application({
    path: req.path,
    onSetTitle: (title) => data.title = title,
    onPageNotFound: () => res.status(404)
  data.body = React.renderToString(component);
  var html = _.template(template, data);

server.listen(server.get('port'), function() {
  console.log('HTTP server is running at http://localhost:' + server.get('port'));

HTML Template for Server-side Rendering

// src/index.html

<!doctype html>
<html class="no-js" lang="">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title><%- title %></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/app.css">
    <!--[if lt IE 8]>
      <p class="browsehappy">
        You are using an <strong>outdated</strong> browser.
        Please <a href="">upgrade your browser</a>
        to improve your experience.
    <%= body %>
    <script src="app.js"></script>

Copy link

wzup commented Jan 14, 2016

Copy link

Copy link

Copy link

nyablo commented Feb 4, 2016

Copy link

Copy link

I have question, sure you will never guess...

Copy link

I had guessed @buscando question and so have same one.

Copy link

Copy link

ghost commented Feb 17, 2016

Copy link

landed1 commented Feb 19, 2016

who is batman ?

Copy link

is this some git bot ?

Copy link

@landed1 Batman is @Waterloo. But I really dont know where he is now

Copy link

aight8 commented May 9, 2016

Copy link

maxpain commented May 26, 2016

Copy link

yookore commented May 28, 2016

So who is answering the question?

Copy link

philipgiuliani commented Jun 17, 2016

Same question as @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177

Copy link

NEX1S commented Jun 17, 2016

Same question as @philipgiuliani, @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177

Copy link

Same question as @philipgiuliani, @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177

Copy link

Just let the server insert an INITIAL_STATE variable into the HTML, then read that variable in the client script and execute a hydrate action. If you have further questions, you can easily reach me on Gitter.

Copy link

maxbook commented Nov 1, 2016

Same question as @philipgiuliani, @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177, @rcolepeterson

Copy link

Same question as @philipgiuliani, @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177, @rcolepeterson, @maxbook

Copy link

igorgolovanov commented Nov 17, 2016

Copy link

@philipgiuliani, @cameronroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer (@imrvelj), @Kaveckas, @evidanary, @dkoleary88 @louwers @komocode @wzup @boyney123 @penakamaayo @NazarYablonskiy @michaelost, @abaoaqus, @buscando, @RusinovAnton @NobleGestures, @lubbertdas, @aight8, @Maxpain177, @rcolepeterson, @maxbook, @o-shabashov, @golovanov

I want to Answer that Question There is More than one DOM in Reality.
Shadow DOM, browser DOM, Other Virtual DOM's,

So first of all the ServerSide Renders and throws that HTML after that the frontend will render also but in a Virtual DOM and it will Only render Objects that are not in the browser DOM and will take Parts from the Browser DOM and will sync both

Keywords for that are Shadow binding, DOM Syncing, and so on bind and attach of DOM Elements.

You can think about a DOM like a normal JAVASCRIPT Object :) so we can easy loop over them.

Hope that makes sense and helped you all to understand.

Copy link

xuezhma commented Aug 29, 2017

Copy link

Copy link

Copy link

Mach12 commented Mar 5, 2018

Copy link

Hopefully, this approach can help you.

Copy link

ondrek commented Jan 28, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment