27 Jun 2017 - by 'Maurits van der Schee'
We currently see that MVVM frameworks like Angular and React are booming in popularity. Not taking anything for granted, I was wondering last week: does "Client side rendering for scalability" even make sense? Is it a beneficial to send JSON over the wire and render it on the client? Does that lower the load on the server, compared to rendering the HTML? How expensive is the HTML templating? Is it more expensive to generate HTML than to generate the JSON it is based on? My feeling says it does, but is it true and how much does it matter?
Although scalability is the only thing I am interested in, let's first take a look at the various pros and cons of client side rendering:
On the upside:
The cost of combining HTML and JSON data is moved from the server to the client. This may have a positive influence on the load on the servers. Also the cachability of the templates increases, which allows for faster delivery of HTML via a CDN or from local cache reducing the bandwidth.
On the downside:
Javascript execution is increasing the client render time often to a point where page loads take seconds. This increases the need for single page applications that in turn load their content often in a cascading fashion and need to render intermediate results and spinners to ensure that the visitor understands that the page is (still) loading. Loaders and intermediate renders that in turn increase the total loading time.
It is a trade-off, but I think we can agree that HTML can be pretty sparse (all assets can be in other files). The overhead will thus not be so big. Both JSON and HTML need escaping so there really is not so much difference. You will use more bandwidth, but what you get in return is more control over the render time of the HTML and an independence of JavaScript.
Here is some (Go) code that actually allows you to benchmark json output versus templating output:
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/shiyanhui/hero/examples/app/template"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
count := 1
u, _ := url.ParseRequestURI(req.RequestURI)
request := strings.Split(strings.Trim(u.Path, "/"), "/")
if len(request) > 1 {
count, _ = strconv.Atoi(request[1])
}
userList := make([]string, 0, count)
for i := 0; i < count; i++ {
userList = append(userList, "Alice")
userList = append(userList, "Bob")
userList = append(userList, "Tom")
}
switch request[0] {
case "html":
template.UserListToWriter(userList, w)
case "json":
b, err := json.Marshal(userList)
if err != nil {
fmt.Println("error:", err)
}
w.Write(b)
}
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
I used the following scripts to benchmark:
ab -c 10 -n 100000 http://localhost:8080/json/200
ab -c 10 -n 100000 http://localhost:8080/html/200
The results:
JSON: 13113 requests/sec @ 52480 Kbytes/sec in 7.6 seconds
HTML: 11036 requests/sec @ 420499 Kbytes/sec in 9.1 seconds
As you can see the output of the HTML is about 10x as large as the output of the JSON, but the performance difference is not so big. NB: When gzip is enabled the HTML is only 5x larger in this specific case.
If the majority of your users are working over 3G and they are mainly sending JSON back and forth, then you may think that switching to server side rendering may severely impact your performance as performance on slow connections is highly impacted by transfer size. But it's typically also these users that are on a mobile device with a slow CPU and where client side rendering may take a long time. Only an actual test case for your application may prove what the experience is of either solution.
Let me give you a calculation example: client side rendering takes 2.5 seconds on slow device, while the JSON and HTML sizes are 5 and 50 Kbyte on a 20 Kbyte per second 3G connection. This means that if the server side rendered page shows in less than 250 milliseconds the server side rendering is faster. I have seen such average numbers in real life applications and I think they are realistic.
I urge you to not take my word for it. If you now do client side rendering, then go and try server side rendering out! You may greatly improve the performance and reliability of your web application while accidentally reducing complexity and improving testability. Do it! What do have to lose?
PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.