Clients side frameworks are great. They can help you build interactive and fast web applications which users love to use.
Unfortunately it is not all roses. There are several drawbacks, too. One of the main disadvantages is the initial loading speed.
Client side frameworks receive very little HTML from the server, but they receive a lot of JavaScript.
Then they have to request and wait for the data that should be rendered. Finally they compute and render everything on the user own machine.
On the other hand, traditional web sites render everything on the server and as soon as HTML is delivered the page is displayed and ready for the user.
Moreover, most web servers can render the page faster than a client side rendering.
As a result, the initial loading is very quick.
React to the rescue
Naturally, you want to have the best of both worlds. Fast initial loading and quick and interactive application. React can help you with that.
Here is how it works. First, it has the ability to render any component, including its data, server side. The result will be some HTML which will be then send to the browser.
Once this HTML is displayed by the user’s browser, React will make the same computations locally. Its smart algorithm will see that the result is identical to what is already displayed on the page.
As a result it will not make any changes. It will only attach the necessary event handlers.
How is this faster? Aren’t we doing almost the same things client side?
Yes, but almost is the keyword here.
First, as soon as the server responds to the browser request, the user will see the page. Therefore the perceived speed is much faster then before.
Second, because React identifies that no change to the DOM is necessary it will not touch it. This is the slowest part of the rendering.
In addition one request is saved, because all the data is served already rendered and React doesn’t need to request it from the server.
Is it possible that when the loading happens the page is displayed but the user is unable to interact with it because the event handler are not yet attached?
Theoretically it is possible. However, with this technique we are avoiding all the costly operations and as a result not only the perceived speed is fast, but the attaching the even handlers happens very quickly.
As a result, your application will be always interactive and your users will not notice any problems.
Examples
Enough talk, let’s see how it all works in practice. Our first example will be a simple one. We want to display a hello message which when clicked shows a notification.
Our examples will use NodeJS for the server part, but everything we see here can be also applied on other platforms and languages like PHP, Ruby, Python, Java or .NET.
We need the following node packages:
We will use express
and jade
to create a server for our example application.
The react
and react-dom
packages will provide the server side rendering for
the React components.
The babel
package can will enable us to load JSX components directly in Node with
require('some-component.jsx')
or require('some-component.js')
.
babel
is actually much more powerful than that. It allows you to use ES6 features
right now.
The application will consist of only 3 files in the following structure:
component.js
will contain our React components. index.jade
will provide the
base site template which loads all the JavaScript and app.js
will be our Node
server.
Let’s see what the index.jade
template contains:
div(id='react-root')!= react
is the most interesting part here. Its purpose is
to contain the root React component. In addition, the react
variable will
contain the HTML of the server side rendered React component.
The first two included JavaScript files are React itself. Then, you also need to include Babel if you would like to use JSX in your components.
The last file included is the components. We let babel know that it should process the file by setting the type to text/babel.
It provides some basic HTML structure and loads all the JavaScript and React components that you need.
Let’s look now at our simple server:
Most of this file is the usual way that you setup an express application. Nothing special. However, there are a few lines that require more attention.
The very first line
hooks Babel to your require. From then, you can require directly react components containing JSX and they will be translated to JavaScript on the fly. Just like in this next line.
The first line loads the React component written with JSX. Then React.createFactory
generates a function which can create HelloMessage components.
This is the part where the React component is rendered and then a web page with it is rendered and sent to the browser.
First a new HelloMessage component is created with the name property John.
Then by using React.renderToString
we render the HTML for the component.
Bare in mind that the component is only rendered, but not mounted, so any methods related to mounting are not called.
After the component is created we pass its HTML to the index template, which displays it as you saw earlier.
Here is what our component looks like:
As you see this look like any other React component, which uses JSX, except at the beginning and at the end. This is where you must take care to make the component work with both the browser and Node.
Advanced Example: Loading Server Data
Real web apps are usually doing much more than what you have seen so far. They often need to interact with the server and load data from it.
However, we don’t want this to happen during the server side rendering.
Let’s make a few small changes to our existing application. First, the template will now also load jQuery, which we will use only for requesting data from the server.
Our server will have one more request path to serve.
The only difference from the previous example is these 3 lines.
All it does, when /name
is requested, is to return the name Paul with a current date.
Let’s look at the most interesting and important part of our app, the React component.
We have added 4 new small methods but everything else is exactly the same as before.
Once the component is mounted every 3 seconds it will request a name from the
/name
and then it will display it.
componentDidMount
and componentWillUnmount
are never called when the
component is rendered, but only when it is mounted.
As a result during the server side rendering they are never called and
loadServerData
is also never called.
These three methods will only execute once the component is mounted which only happens in the browser.
As you see it is very easy to separate the parts that need to happen only in the browser from the rest and still keep all the code together, and it will still be working!
What’s next?
You have learned how to create fast loading React applications with server side rendering. However, my examples are only for a NodeJS server.
If you are using another technology (like PHP, .NET, Ruby, Python or Java), you can still get the benefits of React and server side rendering and this should be your next step to look at.
In addition I use JSX in the browser directly, thanks to Babel, which also affects performance. For production app it will be much faster to turn JSX into JavaScript before serving it to the browser.
I am sure that you can find out how to do that in your favorite language and web framework.
Other articles that you may like