Is server side rendering a good choice for React application

Single page application like react provides a wonderful user experience, however, it comes with two issues:

  1. For user who accesses the website at first time, there is no cache of javascript files in browser, it may take long time to download javascript and execute if react application is huge. Then time to first render is long.
  2. The html is generated on browser by running react javascript, so SEO will be a problem

Server side render (SSR) comes out to address above issues. It sounds great to run react application on server and return rendered html to client, then client can render html directly while client run react application in background, but does not rerender since the generated DOM tree is same. and search engines see html of the page. in the past a year, I wrote nashorn-polyfill and run it in JVM. But it also comes out issues:

  1. It takes long time to render react application on server side. Usually it renders twice, first is to run what api need to run and collect data, (e.g. getDataFromTree in react-apollo, second is to render to html. and second render run after api calls is resolved. For the complex application, it may take more than 1s to render to html and concurrency performance may be 5 pages/second. (There is idle time of waiting api to return data, and that time is used to render other requests). This means it requires significant amount of servers to serve high traffic.
  2. Every page access triggers the server side rendering, even if browser has cache of react application javascript. It may reduce time to first render when there is no cache, but actually increase time to first render after there is cache. Assuming there are two api calls A and B for the page, but they shall run sequentially. When is run at server, server will not render to html until both of them are resolved, but when it runs at client, browser, it runs A and render whatever can be rendered when A resolved, then run B and render again when B resolved. Due to this fundamental difference, it may always has bigger time to first render.

If SEO is not that important for your application, the biggest requirement to do SSR is gone. If it is important, there would be better to have SSR only for search engines, not for human beings. It may redirect the request by web proxy based on user agent (I have not done this, ideally it should work).

(UPDATE: For the authenticated content, it is not necessary to do SSR since search engine can’t crawl it. Then SSR is only for unauthenticated contents which means everyone see same thing, except those contents based on anonymous cookie. A squid may be set up in front of SSR server so that output of every unique url is cached and served, and can reduce significant load on SSR server.)

When comes to render on client only, there are some ways to increase performance and time to first render.

In a complex application, a page may need to generate 10+ api requests. it not only increase burden for server to handle requests, but also also has downside on client that every api call resolved will trigger a re-render, and big network latency contributes more to performance.

In my case, I use GraphQL instead of RESTful API, and I use apollo-clientwhich has a nice feature to batch multiple GraphQL calls in one request.

Is server side rendering a good choice for React application

You may notice X-Run-Time-ms is only 40 ms for 10 GraphQL queries (this is local development environment). Typically backend server need to go through authentication for every request. Having 10 requests means backend server need to go through authentication 10 times, while batching them in one request only need one time.

In React application first render that require authentication, usually it calls api to get user information first, then display menu and content based on user information. this leads to sequence api call pattern, first is api for user information, second is the api for the other content.

How can we avoid this sequence api call to get user information? Think about one type of server-side rendering, rehydrate that SSR returns state of store and client use it as initial state to hydrate the client store (redux in such context). Usually api call to get user information does not depend on anything and same in any time. What if we alway run api of getting user information on server, but not via server-side rendering way. This can be done via traditional server rendering. We can serve the index.html of react application in jsp (in java) and calls api of getting user information and return it as window.__INITIAL_STATE__ .

This turns out great. Most of pages in my react application only generate only one request when refresh the page.

上一篇:使用Nashorn Engine进行React Server-Side Rendering


下一篇:LNMP(Linux+Nginx+PHP+MySQL)生产源码部署实战