- avoiding server-browser round-trips to modify one HTML element
- it is easier to keep the server side stateless if you maintain the state in the browser
We will look at an example with React
To display the HTML, a few steps are needed:
It displays the HTML delivered directly by the server.
With AngularJS, if inline expression are used, the user can see the following for a few milliseconds:
before AngularJS replaces this expression with its computed value.
If the application needs to display some data from the server, it must first request it with Ajax. The data is displayed only after being received by the browser.
(to make the flicker more visible, I introduced a latency of 500 ms to simulate a slow backend)
The user experience is not optimal. The application flickers at each step, as the DOM is changed several times in a few seconds.
Avoiding the flicker effect
On the client side
In the browser, we can mitigate the flicker effect. Some applications show a spinner as long as the page is not ready to be shown. The not-yet-completed DOM is hidden before being shown in one final step.
For example, AngularJS provides the ng-cloak directive. With this directive, AngularJS can hide the HTML as long as it is not ready.
Welcome back to server side rendering
Instead of rendering everything in the browser, it is also possible to first render the page on the server side, serve it when ready, and when updating it on the client side when necessary.
From example, React can render a UI component without any browser with React.renderComponentToString.
And what about the JVM?
In Java, there are a few projects that can save us:
As a proof of concept, I implemented a little play application that uses these projects to pre-render a React component on the server side.
We receive the data from the database:
The result is send to the browser
complete controller code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
serverside.js uses the node.js modules API to render our main component (CommentBox).
It then loads the data given as first parameter in the controller
It renders the CommentBox component to a String and output it to console.log so that the Scala controller can receive the result with
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Drawback with server side rendering
The drawback with pre-rendering the page on the server side is that we have to wait to have all the data before sending the page. In the sample application, I introduced a latency when requesting the data to simulate a slow database.
The browser must also wait long before getting any HTML. The following diagram shows that the application (deployed on Heroku) needs more than one second to deliver the page!
Can we optimize more?
We can optimize this version by sending the first bytes of the HTML page before having any data. When the data is there, we can send the rest of the page.
To implement this, I used the Facebook’s BigPipe concept as presented in the talk “Building composable, streaming, testable Play apps” from Yevgeniy Brikman
Integrate Play and trireme
It would be easier if trireme would use a FileSystem object, but this API is only available from Java 7.
To wordaround this, I configured the SBT Universal plugin to deploy the public assets to the file system:
- in build.sbt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
This proof of concept shows that it is already possible to achieve that. And I guess it will be even easier in the future.
If you need more information, the code is available on github.