There is a push to change the word Isomorphic to Universal. Whatever floats your boat!
See full post on ReactJS News
Shared JavaScript that runs on both the client & server.
JavaScript driven MVCs (angular, ember, backbone, etc.) render on DOM load, this can be really slowwwww & can make for a bad user experience.
Another major problem is that they aren't indexable by search engines (without paying $$ for a third party service like https://prerender.io/). If your app is serving any kind of data that people might be searching for, this is a bad thing.
When you render JavaScript on the server side you can solve these problems and be super cool while doing so!
- Better overall user experience
- Search engine indexable
- Easier code maintenance
- Free progressive enhancements
I've built a live example of isomorphic JS for you to check out here: https://github.com/DavidWells/isomorphic-react-example
The demo uses the griddle react component to show how you can have apps with large data sets indexed by search engines and thus easier to find by potential users in search engines.
https://www.youtube.com/watch?v=8wfY4TGtMUo
In /server.js install the jsx transpiler:
// Make sure to include the JSX transpiler
require("node-jsx").install();
Then change components to Node friendly syntax where you module.exports the component if it's in a seperate file
Also make sure to React.createFactory
your component for it to be rendered server side
/** @jsx React.DOM */
var React = require('react/addons');
/* create factory with griddle component */
var Griddle = React.createFactory(require('griddle-react'));
var fakeData = require('../data/fakeData.js').fakeData;
var columnMeta = require('../data/columnMeta.js').columnMeta;
var resultsPerPage = 100;
var ReactApp = React.createClass({
componentDidMount: function () {
console.log(fakeData);
},
render: function () {
return (
<div id="table-area">
<Griddle results={fakeData} columnMetadata={columnMeta} resultsPerPage={resultsPerPage} tableClassName="table"/>
</div>
)
}
});
/* Module.exports instead of normal dom mounting */
module.exports.ReactApp = ReactApp;
/* Normal mounting happens inside of /main.js and is bundled with browserify */
Now the magic happens with routes using React.renderToString
inside /app/routes/coreRoutes.js:
var React = require('react/addons');
var ReactApp = React.createFactory(require('../components/ReactApp').ReactApp);
module.exports = function(app) {
app.get('/', function(req, res){
// React.renderToString takes your component
// and generates the markup
var reactHtml = React.renderToString(ReactApp({}));
// Output html rendered by react
// console.log(myAppHtml);
res.render('index.ejs', {reactOutput: reactHtml});
});
};
The reactOutput
variable is then passed into the template:
<!doctype html>
<html>
<head>
<title>React Isomorphic Server Side Rendering Example</title>
<link href='/styles.css' rel="stylesheet">
</head>
<body>
<h1 id="main-title">React Isomorphic Server Side Rendering Example</h1>
<!-- reactOutput is the server compiled React Dom Nodes -->
<!-- comment out reactOutput to see empty non indexable source in browser -->
<div id="react-main-mount">
<%- reactOutput %>
</div>
<!-- comment out main.js to ONLY see server side rendering -->
<script src="/main.js"></script>
</body>
</html>
Because the files are .js and not .jsx, the React.createFactory
has to be used when including components. See why here: https://gist.github.com/sebmarkbage/ae327f2eda03bf165261
If you would like to download the code and try it for yourself:
- Clone the repo:
[email protected]:DavidWells/isomorphic-react-example.git
- Install packages:
npm install
- Launch:
node server.js
- Visit in your browser at:
http://localhost:4444
- To see serverside rendering, comment out main.js from the /views/index.ejs file. This will show what is rendered purely from the server side.
Build changes with gulp
- Server/Client With React, Part 1: Getting Started
- Server/Client With React, Part 2: The Build System
- Server/Client With React, Part 3: Frontend Server