TQ
dev.com

Blog about software development

Subscribe to RSS

Client side rendering is a lie

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?

Pros and cons of client side rendering

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:

Reasons to apply client side rendering

  1. Scalability: using the CPUs in the client devices for templating
  2. Modularity: micro-service architecture with JSON APIs
  3. Workflow: Front-end and back-end work can be done independently
  4. Cachability: more data is static and can be cached (by a CDN)
  5. Real-time: some components never change while others need live updates
  6. Bandwidth: better caching and selective updates cause less data traffic

Reasons to NOT apply client side rendering

  1. Complexity: a single run-time (on the server) is easier to debug
  2. Testability: automating cross-browser tests executing JavaScript is hard
  3. Performance: mobile devices may execute JavaScript quite slow
  4. Search Engines: apparently they still don't like JavaScript

Scaling with client side rendering in theory

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.

Scaling with client side rendering in practice

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.

A code example

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.

HTML file sizes

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.

Be skeptical!

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?