Translation of the article “Building robust web apps with React: Part 4, server-side rendering”, Matt Hinchliffe
From the translator: this is the fourth part of the series of articles “Building robust web apps with React”
Translations:
A few months ago I wrote the
first part of this series , I was very interested in the possibilities of using React to create intelligent applications that can avoid the weaknesses that exist in many modern JavaScript applications. Finally, I'm going to make
my application run first on the server, and then run the same code in the browser, completing the loop of an isomorphic or adaptive hybrid application.
In the
previous part of this series, I wandered around in search of a testing strategy, and this part is not much different. And although there are examples and basic demo of isomorphic JavaScript, there are not so many open source implementations to learn. Towards the implementation details, for me, the biggest difference from writing client-side JavaScript is that I initially have the data.
Reorganization of data flow
The browser version of my Tube Tracker application has a very simple data flow model, but this model is not entirely suitable for the server side. In the browser, data is requested by an AJAX request as soon as the application loads, but an isomorphic application must provide ready-made HTML pages to the browser.
')
The React application has one access point to the component stack — the root component is drawn by the
renderComponent
or
renderComponentToString
, so the data must flow to the top of the stack and be sent down. This goes against
ordinary thinking when working with React, since the data should be processed only by the component that needs it.

Since the data comes down the stack, components that were originally supposed to request data can now use the
getInitialState
method as preload data. Otherwise, the components do not change, except that the initial state loading stage is skipped.
The data provided to the root of the application on the server side
must also be obtained on the client side , if the application must be loaded without the same data provided on the client side, then it will be re-branded to its initial, empty state. The easiest way to provide the initial data is to generate them into the script element, and then pick them up when the application is initialized:
React on server
Components that use plain JSX syntax must be transformed into plain JavaScript before use, but on the server this does not necessarily mean a precompile step. The
React Tools library can transform on the fly. And it is packaged in a
Node-JSX package that transparently interprets the modules as they are needed. Node-JSX needs only a one-time connection to the application, since the
require
method works globally, but use this carefully: the parser used by the React Tools library can rest on some particularly creative aspects of using JavaScript, so for security and performance reasons, it’s better to pull components in files with the extension
.jsx
.
The component stack is generated in the same way as in the browser, but instead of creating a dynamic tree, only the HTML string is needed. For these purposes, React provides the
renderComponentToString
method, it simply runs the
getInitialState
and
componentWillMount
methods for each component. Components should be translated to the server without causing problems, unless browser-browser code is used anywhere, so make sure that all client code is moved to the
componentDidMount
method.
The rest is on the server
The last few steps to provide the initial HTML code to the browser are in a specific implementation, but for reference, I will quickly go through the backstage implementation of the Tube Tracker application.
The application has already used
Express to provide static assets, I added an additional route to process requests and respond to them with static HTML. This route, if needed, makes a request to the API and drives the data into the template loaded from the file system:
The template module is extremely simple; it loads the requested file from the disk and replaces the placeholders with the transferred data. It makes no sense to use a more complex library for templating, since all this template engine will work with are two small pieces of data:
Due to browser incompatibility, it is
no longer possible to create a complete HTML document using React components. It would be possible not to do this on the server, but it would be strange to create components that are differently arranged on the backend and the frontend.
I took the opportunity to replace the old and unfriendly TrackerNet API with the new TfL REST API. This replacement slightly reduces the complexity of the work, since it avoids working with XML, but the more convenient JSON data for use from the new API is returned unsorted and lacking some useful information. For this reason, I built a small proxy to sort and add additional useful data. In the future, you can add an interlayer to cache and prevent unnecessary calls to the API.
Conclusion
Building applications that should run on the server and in the browser was an interesting adventure. React is a great tool for building client applications and it gives you great productivity because with it, it’s really easy to build dynamic applications. With careful planning, he will help turn the fragile client-side JavaScript application into a reliable, working product. However, for now, I do not strongly recommend isomorphic JavaScript applications; The increased complexity of development has turned the construction of the Tube Tracker application into hard work. The browser version of the application took several hours of development, and the server version even less, but structuring and abstracting the code to run the applications as a whole took many times longer than expected.

A relatively small amount of project code is divided between the two environments, only well-abstract utilities and React components have been transferred.
Undoubtedly, the time spent on building isomorphic applications will decrease as soon as this process becomes more frequent and new templates appear, but now I’m worried that the extra effort spent is just a developer’s whim. If the application generated on the server is sufficiently functional, then there is no really convincing argument that the user experience will be improved by loading and executing a large amount of JavaScript that only repeats the application that the user already has.
The efforts of web developers to repeat the behavior of applications for smartphones led to a frantic revolution in the technologies we used and we learned a lot in using the web as a platform for delivering all kinds of content. Some of the features and techniques that have emerged that are isomorphic to JavaScript are very interesting, but building new web products continues to be increasingly difficult.
I really like React, it's a great tool, but I like it when it's simple.
You can
try the finished application right now (note: the example is running on a free account, so this link may be unstable) or go to GitHub to
view the source code . Please comment or
tweet me , I will be happy to receive feedback.