Skip to content

Instantly share code, notes, and snippets.

@koistya
Last active September 15, 2023 07:32
Show Gist options
  • Star 90 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save koistya/24715d295fbf710d1e24 to your computer and use it in GitHub Desktop.
Save koistya/24715d295fbf710d1e24 to your computer and use it in GitHub Desktop.
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

@digitalashes
Copy link

@Mach12
Copy link

Mach12 commented Mar 5, 2018

@rohail-kalyar-pakwheels
Copy link

All,
Hopefully, this approach can help you.

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

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