Skip to content

Instantly share code, notes, and snippets.

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

Files

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);
    this.props.onSetTitle(page.title);
    
    return (
      <div className="container">
        <h1>{page.title}</h1>
        <div>{page.content}</div>
      </div>
    );
  }
});

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);
  res.send(html);
});

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="">
  <head>
    <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">
  </head>
  <body>
    <!--[if lt IE 8]>
      <p class="browsehappy">
        You are using an <strong>outdated</strong> browser.
        Please <a href="http://browsehappy.com/">upgrade your browser</a>
        to improve your experience.
      </p>
    <![endif]-->
    <%= body %>
    <script src="app.js"></script>
  </body>
</html>

Example

https://github.com/kriasoft/react-starter-kit
@cameronroe

This comment has been minimized.

Copy link

cameronroe commented Feb 8, 2015

How does this work with data from the server after the client re-renders the component?

@jeremyeast

This comment has been minimized.

Copy link

jeremyeast commented Aug 4, 2015

Same question as @cameronjroe

@MelkorNemesis

This comment has been minimized.

Copy link

MelkorNemesis commented Sep 30, 2015

Same question as @cameronjoe & @jeremyeast.

@aayler

This comment has been minimized.

Copy link

aayler commented Sep 30, 2015

@hvalls

This comment has been minimized.

Copy link

hvalls commented Nov 5, 2015

@lasekio

This comment has been minimized.

Copy link

lasekio commented Nov 7, 2015

@imrvelj

This comment has been minimized.

Copy link

imrvelj commented Nov 13, 2015

@mantaskaveckas

This comment has been minimized.

Copy link

mantaskaveckas commented Nov 30, 2015

@evidanary

This comment has been minimized.

Copy link

evidanary commented Dec 11, 2015

Same question as @cameronjroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas

@dkoleary88

This comment has been minimized.

Copy link

dkoleary88 commented Dec 18, 2015

Same question as @cameronjroe, @jeremyeast, @MelkorNemesis, @aayler, @bigdestroyer, @Laskos, @perpaer, @Kaveckas, @evidanary

@louwers

This comment has been minimized.

Copy link

louwers commented Dec 27, 2015

@komocode

This comment has been minimized.

Copy link

komocode commented Jan 10, 2016

@wzup

This comment has been minimized.

Copy link

wzup commented Jan 14, 2016

@boyney123

This comment has been minimized.

Copy link

boyney123 commented Jan 18, 2016

@penakamaayo

This comment has been minimized.

@NazarYablonskiy

This comment has been minimized.

@michaelost

This comment has been minimized.

@sergeydevhub

This comment has been minimized.

Copy link

sergeydevhub commented Feb 5, 2016

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

@RusinovAnton

This comment has been minimized.

Copy link

RusinovAnton commented Feb 7, 2016

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

@mualimual

This comment has been minimized.

@ghost

This comment has been minimized.

Copy link

ghost commented Feb 17, 2016

@landed1

This comment has been minimized.

Copy link

landed1 commented Feb 19, 2016

who is batman ?

@lakshmantgld

This comment has been minimized.

Copy link

lakshmantgld commented Feb 24, 2016

is this some git bot ?

@sirajulm

This comment has been minimized.

Copy link

sirajulm commented Apr 23, 2016

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

@aight8

This comment has been minimized.

Copy link

aight8 commented May 9, 2016

@Maxpain177

This comment has been minimized.

@yookore

This comment has been minimized.

Copy link

yookore commented May 28, 2016

So who is answering the question?

@philipgiuliani

This comment has been minimized.

Copy link

philipgiuliani commented Jun 17, 2016

@NEX1S

This comment has been minimized.

@rcolepeterson

This comment has been minimized.

@FlorianWendelborn

This comment has been minimized.

Copy link

FlorianWendelborn commented Jun 28, 2016

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.

@maxbook

This comment has been minimized.

@igorgolovanov

This comment has been minimized.

@frank-dspeed

This comment has been minimized.

Copy link

frank-dspeed commented Feb 21, 2017

@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.

@rohail-kalyar-pakwheels

This comment has been minimized.

Copy link

rohail-kalyar-pakwheels commented May 7, 2019

All,
Hopefully, this approach can help you.

https://fluxible.io/blog/2014-11-06-bringing-flux-to-the-server.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.