Simplifying client-server development with Server-Side Client (SSC) architecture

jolon
6 min readApr 17, 2019

Client-Server development is hard.

If we look at the evolution of software development from the beginning to around the 1990s, software development generally became easier and end-users were increasingly able to develop advanced software. The pinnacle was development environments like Apple’s HyperCard and Microsoft’s Visual Basic.

Developer ease of use peaked in the late 1980s and early 1990s and decreased as client-server architectures became more common.

This trend came to a screeching halt with the advent of the web. The web originally was a server-side architecture where all of the logic existed on the server. The user experience was much poorer than client-side-only applications. Web 2.0 began to address this by moving more logic to the client. The result was a major move towards client-server programming like we hadn’t seen previously. This provided a rich user experience whilst also supporting multiple users connected to a centralised server.

The challenge with client-server programming is that it is inherently very difficult. Apps that would’ve been easy to build for end-users using HyperCard in the 1980s now require top computer science programmers. Bill Atkinson, the creator of HyperCard, opined that if he had’ve considered the network, HyperCard may have succeeded instead of HTML. However, this is a simplistic view, and it could be argued that HTML’s success is because it moved the logic to the server which HyperCard was unlikely to do.

Client-server programming is challenging for a few reasons. One is that the server frameworks are often different to the client so it requires the developer to be simultaneously developing in two quite different environments. It also requires the developer to be familiar with concepts such as asynchronous programming, websockets, synchronisation, and so on. It also doesn’t help that there aren’t many frameworks that directly address the client-server architecture, it is generally up to the developer to roll their own from multiple frameworks.

One ambitious framework that attempted to simplify client-server programming is the Meteor framework which launched in 2012. Meteor addresses almost all of the client-server issues, it allows the same code to run on both the client and the server, updates to data on the server can be automatically propagated to the client and update the DOM. Meteor have their own client-server protocol called DDP which is hidden from the developer. The architecture is clever but unfortunately ahead of its time and development hasn’t kept up with recent developments in web frameworks. In addition one major criticism I have of Meteor is that it remains client-side heavy.

The Solution: Server-Side Client (SSC)

Recently it occurred to me that if all of the logic could be moved to the server it would greatly reduce the cognitive burden of client-server development. But how do we have a rich user experience if the logic is on the server?

My proposed Server-Side Client (SSC) architecture consists of a client-side JavaScript library that serves two purposes:

  1. Receives DOM updates from the server and updates the client-side DOM
  2. Sends events from the client to the server

In essence the browser becomes like a fancy terminal interface. It merely handles graphical updates and sends input from the user back to the server.

The server would maintain a DOM representation of each connected client and handles all logic, user events, and DOM updates.

This greatly simplifies client-server development. The coding complexity could be reduced to tools like HyperCard and Visual Basic.

SSC issues

The SSC architecture introduces a number of issues. The first is latency. Since all logic is handled on the server, the response time can be no faster than the latency of the connection. Users in Australia experience a latency of about 300ms to servers in the US. That is a limit of 3 frames per second.

Another issue is server-side resources. The server must maintain open connections to all connected clients, the server must maintain a complete DOM representation of what the client sees, and the server handles ALL of the client logic. This is a significant load on memory and CPU.

A final issue is that a server-side approach will always require a connection and prevent the development of client-only apps. However, client-only apps could be achieved with the same architecture by providing a client-only version of the framework, if it is required.

Addressing SSC issues

The issues mentioned above are not deal breakers. If SSC can significantly lower the barrier to entry for modern software development, then poorer performance in some areas may be outweighed by the improvement in productivity. Nonetheless lets address some of them.

Latency

I see two ways to address latency.

Firstly, servers can be deployed to the cloud in locations closer to the user. A user in Australia should connect to a server in Australia. The latency would then reduce to about 30ms, or 10x less, resulting in a maximum framerate of 30fps, which should be acceptable.

Secondly, techniques can be used to make interactive tasks more responsive. For example, CSS should be used where possible to provide immediate feedback (e.g. on hover). Additionally, the SSC framework could provide standardised implementations of common client-side tasks which require immediate feedback that are not currently provided by HTML/CSS and also don’t require client-server complexity from the developer.

Finally, the approach doesn’t exclude client-side code. If the developer was implementing a game, they could implement the interactive elements of the game client-side, whilst the remainder of the logic is implemented server-side.

Server-side Resources

Server-side resources will certainly increase. However, it is the trend of web development that server-side resources do increase over time, generally to simplify development. So reduced development complexity and increased server resources has generally been an acceptable tradeoff depending on the application.

I imagine that the SSC approach would largely be used for rapid application development and for projects with a smaller number of users. That is not to say that it couldn’t be used on a larger scale, however in these smaller applications the resource usage would be sufficiently small that it may not even be apparent that extra resources are required by the SSC approach.

Potential Architecture based on Node.js

Node.js would serve a basic HTML document to the client with the JS library which handles the communications protocol with the server. No other JS is sent to the client (although this is not a restriction, and may occur, e.g. if web components are used).

A Node-based SSC framework can be based on express and use either Server-Sent Events (SSE) or websockets.

When a new connection is made for SSE or websockets, Node creates a new Client instance.

The framework would use a component architecture similar to Angular. A page component would represent the entire page, and each component has an associated HTML template. An app built using this framework would specify a root or initial page component. An instance of the page component would be created on first connection and the associated template loaded into a DOM hierarchy with DOM updates sent to the client representing the initial page component template state. Just like Angular, other component classes can be created with their own templates.

The templates would allow events on components to be bound to functions. The functions are implemented in the component, and executed on the server. When an event occurs on the client, it sends the event back to the server, and the server executes the function on the respective component. Changes to the DOM as a result of the event handler are then propagated back to the client for display to the user.

If server-side events are used, the client would send a single GET request to open up the event stream from the server. However to send event updates from the client, the server would need to implement a separate POST request handler to process client events. The event request would need to create an id of the client so that the client instance can be found on the server and the event sent to the correct component.

If websockets are used then the connection remains open for both sending and receiving. Each client would register an event handler with the appropriate websocket so that it automatically receives events destined for it.

Websockets are more efficient, however server-side events may suit scenarios where HTTP protocol is required (or more specifically where non-HTTP protocols are restricted).

Future

Initially the basic architecture as outlined in the previous section would need to be implemented. It would be analogous to implementing Angular on the server. Angular however, is relatively complex to develop for, and this alone will not necessarily attract less technical developers. However, this initial architecture would allow for something like HyperCard or Visual Basic to built on top of it in the future, creating a lower barrier of entry for all developers.

--

--