Isomorphic React with node.js

Tom Howell
3 min readFeb 16, 2016

--

Isomorphic what?

Simply, it’s a fancy way of saying we’re going to render our React code server side as well as on the client.

Why?

  • Your dynamic JS is now search engine indexable, yay!
  • Better overall user experience.
  • Performance benefits.

Lets break it down

If you’d like to see the full source code for this article, you can find it here: https://github.com/tomshowell/Isomorphic-react-node

All we’re going to do here is create a component that renders a summary of a news article (title and date) from a static JSON file, both on the server and on the client.

/components/News.jsx

import React from ‘react’;class News extends React.Component {

constructor() {
super();
}
render() { let newsArticles = this.props.newsData.map(function(n) { return (
<blockquote>
<p>{ n.title }</p>
<footer>{ n.date }</footer>
</blockquote>
);
});return(
<div>
{ newsArticles }
</div>
);
}
}export default News;

This is the easy bit. News.jsx takes the JSON data as its props and maps that to a block quote that display the title and the date.

/components/News_Client.jsx

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import News from ‘./News’;let props = JSON.parse(document.getElementById(‘props’).innerHTML);ReactDOM.render(
<News newsData={ props } />,
document.getElementById(‘news-mount’)
);

Nothing too unusual here in importing our component and mounting it to a div. This line:

let props = JSON.parse(document.getElementById(‘props’).innerHTML);

will get our JSON data which we pass as props. We’ll cover how this gets populated in routes/routes.js.

/views/index.ejs

<!doctype html>
<html>
<head>
<title>Isomorphic React with node.js</title>
<link href=’https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' rel=”stylesheet”>
</head>
<body>
<div class=”container”><h1 id=”main-title”>Isomorphic React with node.js</h1><br /><br /><div id=”news-mount”><%- output %></div></div><script type=”application/json” id=”props”><%- jsonProps %></script><script src=”/newsClient.js”></script></body>
</html>

If you’re this far down the article then you probably know what the above does. The only two things we've added over a traditional React application are

<div id="news-mount"><%- output %></div>

The output tag will take the News components rendered html which we will pass through in our routes.js.

<script type=”application/json” id=”props”><%- jsonProps %></script>

Remember that line in our News_Client.jsx where we parsed JSON out of a div? Well this is where we set it. Again we will pass through jsonProps in our routes.js.

/routes/routes.js — Where the magic happens

If you found the rest of the code simple and easy to follow then this is going to be no different. Let’s take a look at our route.

var React = require(‘react’);
var ReactDOMServer = require(‘react-dom/server’);
var request = require(‘request’);
var url = require (‘url’);
News = React.createFactory(require(‘../components/News’).default);module.exports = function(app) {app.get(‘/’, function(req, res) {request(‘http://localhost:8888/news.json', function(err, resp, body) {var html = ReactDOMServer.renderToString(News({ newsData: JSON.parse(body) }));res.render(‘index.ejs’, { output: html, jsonProps: body });

});
});}

To render our component server side we first need to include it

News = React.createFactory(require(‘../components/News’).default);

What follows will be wrapped in a request request (? really) that will be executed once we have got our news data.

The following line takes our component and with React’s built in function, renders it to a string, passing the JSON data from the request as the newsData property.

var html = ReactDOMServer.renderToString(News({ newsData: JSON.parse(body) }));

Remember those variables in our view file? This is where we pass them. We will pass our string rendered React component and the JSON data to our view.

res.render(‘index.ejs’, { output: html, jsonProps: body });

That’s it

And we’re done. If you CD to your project directory and run

node app.js

it will start the server up on http://localhost:8888

If you view source (not inspect element), you’ll notice your news titles and dates rendered in the code, good or what!

Additionally, you’ll notice if you comment out

<script src=”/newsClient.js”></script>

In views/index.ejs your news title and dates still get rendered.

I hope you enjoyed this article and can see that isomorphic React doesn't have to be hard! If you have any questions, don’t hesitate to leave them in the comments.

--

--

Tom Howell

Front end developer and aspiring entrepreneur trying to do something memorable.