Original:
React To The Future With Isomorphic AppsIsomorphic applications. Looking to the future with React
In software development, everything often returns to normal. For example, at the dawn of the development of the Internet, servers loaded the content immediately to the client. Recently, with the development of modern web frameworks such as AngularJS and Ember, we see a tendency to process requests on the client side and use the server only for the API. However, this is not the only trend. Now there is a slow return, or rather a merger of these two architectures.
What is React?
If you use the definition from the
official site , then
“React is a JavaScript library that is used to create user interfaces.”
With React, you can create reusable components in web development. Moreover, the components are created easily and simply. This, in fact, is the goal of React.
')
What makes React special?
React quickly became popular among JavaScript developers, and there are a number of reasons for this. One of them - React was developed by Facebook and now it is actively promoted and used. This means that developers working with Facebook actively use React: they program, fix bugs, develop new functionalities, etc.

Another reason for the rapid popularity of React is that it is very different from AngularJS, Backbone.js, Ember, Knockout and other well-known MV * JavaScript frameworks that have appeared like mushrooms after rain in the last few years. Most of these frameworks work on the DOM double binding scheme and update it depending on the events. To use them, the presence of a DOM is mandatory, so when you work with one of these frameworks and want to render the markup on the server, you will have to use PhantomJS or something similar to it.
Virtual dom
If we consider the abbreviation MVC (model-view-controller), then React - rather, can be attributed to “V”, that is, to “view”. However, React performs a view function that is different from other MV * frameworks. For example, it has nothing to do with Handlebars, Underscore and AngularJS templates. React's work is based on the concept of a “virtual DOM”. React keeps a virtual DOM in memory and every time it is modified, it differentiates them quickly, reduces them to one update and sends a whole data packet to the real DOM.
This approach has a number of advantages, the main of which is a significant improvement in performance. You do not need to constantly update the DOM, as in other JavaScript frameworks. In addition, React can process requests both on the server side and on the client side without any problems.
React uses a method called React.renderToString (). It allows you to pass a component, which, in turn, processes it together with the child element used and returns the code. You can simply take this HTML code and send it to the client side.
Example
The following components are built on JSX. At first glance it may seem that JSX is similar to a hybrid of HTML and JavaScript:
var HelloWorld = React.createClass({ displayName: "HelloWorld", render() { return ( <h1>Hello {this.props.message}</h1> ); } }); React.render(<HelloWorld message="world" />, document.body);
Now you need to skip (or translate) .jsx via a webpack, grunt, gulp or an alternative engine and get a JavaScript code like this one:
var HelloWorld = React.createClass({ displayName: "HelloWorld", render: function() { return ( React.createElement("h1", null, "Hello ", this.props.message) ); } }); React.render(React.createElement(HelloWorld, {message: "world"}), document.body);
This is the code we get using HelloWorld.jsx. As you can see, this is regular javascript. Of course, you can argue that you can't mix HTML and JavaScript, that this is a mistake; however, it only seems so at first glance. Having worked with React, you understand that the proximity of markup components allows you to write code faster and make it more voluminous and consistent. It turns out that you do not have to constantly switch between HTML and JavaScript files - and all the code for the developed component is in one place.
React.render attaches the HelloWorld component to the body. Obviously, any item can be added there. It calls the component's render method, and therefore the result is added to the DOM inside the body tag.
In any component of React, whether you passed attributes or not — for example, HelloWorld message = ”world” —you have access to this.props component. Therefore, in the HelloWorld component, this.props.message will be world. So pay attention to the following part of the JSX code:
return ( <h1>Hello {this.props.message}</h1> );
You will notice that the HTML is wrapped in parentheses. Then, this.props.message needs to be wrapped in braces that allow access to the component through this.
In addition, each component has access to its “state”. In React, each component can manage its state using several simple API methods, such as getState, setState, getInitialState. The latter is used during component initialization. Whenever the state changes, the render method will render the component. For example:
var Search = React.createClass({ getInitialState() { return { search: "" }; }, render() { return ( <div className="search-component"> <input type="text" onChange={this.changeSearch} /> <span>You are searching for: {this.state.search}</span> </div> ); }, changeSearch(event) { var text = event.target.value; this.setState({ search: text }); } }); React.render(<Search />, document.body);
In the example above, the getInitialState function returns a simple object literal containing the initial state of the component.
The render function returns JSX for our elements, it means input and span, both wrapped in a div. Do not forget, in JSX only one item can be returned as a parent. In other words, you cannot return a div twice; You can return only one item with many children.
Pay attention to onChange = {this.changeSearch}. This command allows the component to run the changeSearch function upon data entry.
The changeSearch function receives the event triggered by the DOM event and receives the entered text. Then, we make a request for setState and pass the text, which launches the render, and {this.state.search} displays the changes that have appeared.
In React, you can work with many different APIs. However, when working at a high level, the method described above will be enough to create simple components.
Isomorphic javascript
With the help of React, we can create so-called “isomorphic” applications. The word “isomorphic” has already gained popularity in 2015. In simple terms, “isomorphism” is that we can use the same code both on the client side and on the server side. Obviously, this approach has many advantages.
Getting rid of FOUC
When using AngularJS, Ember and SPA architecture, when the user first hits the page, all its elements are loaded. In SPA applications, the download may take several seconds, and most users today expect at least 2 seconds. While the content is loading, the rendering of the page does not begin. This delay is called FOUC (flash of unstyled content). One of the main advantages of the development of an isomorphous method is that the speed of loading elements is significantly accelerated due to simultaneous rendering on the server side and on the client side.
It turns out that the task of an isomorphic application is not to replace the usual server API, but to get rid of the stream of non-stylized content, thereby improving the user experience with the page (and their requests are constantly growing).
Same code
A solid advantage of isomorphic applications is the ability to use the same code on the server side and on the client side. Just create the components you need and they will work there and there. In most other systems, such as Rails, Asp.NET MVC, you have erb and cshtml for server-side rendering. In addition, you need to use templates such as Handlebars or Hogan.js, which often duplicate logic. In React, the same components work equally well on the server side and on the client side.
Process improvement
Server-side rendering allows you to quickly send the HTML skeleton needed by the client to view the site. Then, you can enhance the picture by processing more items on the client side.
As a rule, to provide the same comfort from viewing the page or using the application for a user with the simplest “clamshell” from Africa and a user with the latest McBook Pro with Retina display and connecting to the last 4k monitor is not an easy task.
In React, things are a little more complicated than just passing on different components. When you process React components on the server side and send a skeleton of HTML code to the client, React on the client side finds similar HTML code and attaches containers with events to existing elements. Voila!
This means that it is enough to send only the part of the HTML code that is necessary for rendering the page. All additional items can be retrieved and processed on the client side. You get an advantage in the form of fast loading from the server side, and also in the form of the possibility of re-using the same components.
Create an isomorphic application on Express
Express is one of the most popular Node.js web servers. Raising and running the application on Express using React is not a problem.
Adding React rendering to Express consists of several steps. First you need to add node-jsx and react to the project as follows:
npm install node-jsx --save npm install react --save
Next, you need to create a base app.jsx file in the public / javascripts / components directory. For this we need the Search component that we used earlier:
var React = require("react"), Search = require("./search"); var App = React.createClass({ render() { return ( <Search /> ); } }); module.exports = App;
Here we need react and component Search.jsx. In the render method, the App component, we can simply use the component with Search.
Then you need to add the following code to one of the routers in which you plan to render using React:
require("node-jsx").install({ harmony: true, extension: ".jsx" });
This will require to use .jsx files. Otherwise, Node.js will not understand how to parse them. The harmony option allows you to use ECMAScript 6 components.
Then, you need to query the component and send it to React.createFactory, which will return a function with which you can call the component:
var React = require("react"), App = React.createFactory(require("../public/javascripts/components/app")), express = require("express"), router = express.Router();
Then, in the route itself, list React.renderToString and pass the component:
router.get("/", function(req, res) { var markup = React.renderToString( App() ); res.render("index", { markup: markup }); });
Finally, get the output for the markup in the preview tab:
<body> <div id="content"> {{{markup}}} </div> </body>
That's all for the code on the server side. Now let's see what needs to be done on the client side.
Webpack
Webpack is a JavaScript packer that allows you to collect static objects (JavaScript, CSS, images, etc.) into one file, as well as to process files using various downloaders. You can write JavaScript code using CommonJS or the syntax of AMD modules.
For React .jsx files, you will need to slightly configure the webpack.configure file to compile all jsx components.
Getting started with Webpack is easy:
npm install webpack -g # Install webpack globally npm install jsx-loader --save # Install the jsx loader for webpack
Then, you need to create a file webpack.configure.js.
var path = require("path"); module.exports = [{ context: path.join(__dirname, "public", "javascripts"), entry: "app", output: { path: path.join(__dirname, "public", "javascripts"), filename: "bundle.js" }, module: { loaders: [ { test: /\.jsx$/, loader: "jsx-loader?harmony"} ] }, resolve: {
Now consider the above code. Here we have:
- context. This is the root of your javascript files.
- entry. This is the main file that will load other files with require in CommonJS by default.
- output. Tells the Webpack command to issue a code in a single file using the public / javascripts / bundle.js chain.
The module object allows you to configure loaders. The loader also allows you to test file extensions, and then transfer it through the loader. There are many loaders for CSS, Sass, HTML, CoffeeScript and JSX, but in this case we need only one - jsx-loader? Harmony. You can attach options such as “query string” to the bootloader name. In this case,? Harmony allows you to use ECMAScript 6 syntax in our modules. test tells Webpack to transfer any file with the .jsx extension to the jsx-loader.
In resolve, we see a slightly different picture. First, extensions instructs Webpack to skip files with extensions of certain types when we prescribe require. Because of this, we can use require (“./ file”), and not require (“./file.js”). In addition, we specify root, which, in essence, is simply the root from which files will be extracted. Finally, we allow Webpack to extract modules from the node_modules directory using modulesDirectories. So, we can install, for example, Handlebars using npm install handlebars and require (“handlebars”), as well as in the applications on Node.js.
Client side code
For public / javascripts / app.js, we will need the same App component that we used in Express:
var React = require("react"), App = React.createFactory(require("components/app")); if (typeof window !== "undefined") { window.onload = function() { React.render(App(), document.getElementById("content")); }; }
Check that we are in the browser using the typeof window! == ”undefined” command. Then, attach window events to onload, call React.render and transfer to the App (). Next, we need a DOM element to load. This should be the same element that we used in the server-side React markup, i.e. #content.
The Search component from the example above was processed on the server and sent to the client. The client-side React accepts rendered markup and attaches event containers to it! This means that we can easily view the page while JavaScript is still loading.
All the code presented in the article
is available on GitHub .
Conclusion
Web architecture develops in cycles. At first, rendering took place only on the server side and then sending data to the client. Then, JavaScript appeared, and we began to use it for simple operations on the page. Finally, JavaScript has evolved so much that it has become possible to use it to create large applications that will render on the client side and use the server to extract data through the API.
In 2015, we began to realize that we have at our disposal powerful servers that have enough processors and memory to process almost any data. An isomorphic approach to application development can give us the best of two worlds: we can use JavaScript both on the server side and on the client side, which increases download speed and allows users to see information on the page faster as additional elements are loaded onto client side.
React is one of the first frameworks that are no doubt already numerous, which implements this kind of behavior. Ember developers are already working on isomorphic applications. I am sure that it will be very interesting to watch the development of these frameworks!
about the author

Jonathan Creamer is a senior web developer at Lonely Planet. He is interested in JavaScript, in particular, the architecture of web applications and development on Node.js. In addition, he has extensive experience with ASP.NET MVC, Ruby on Rails, and ColdFusion. Jonathan started web development at the age of 13 when he went to work at one of the start-ups in Franklin, Tennessee. Then he went to study at a developer at Middle Tennessee State University. He currently lives in Murfreesboro, Tennessee, with his wife and daughter.
Worked on the translation:
greebn9k (Sergey Gribnyak),
seninrom (Roman Senin),
silmarilion (Andrey Khakharev)
Singree