This article looks at a new approach for achieving a Single-page Application (SPA) -- HTML over WebSockets.
This article has been translated and adapted from the original Spanish version.
Contents
What is it?
The traditional way to achieve a Single-page Application (SPA) is to divide responsibilities between the back and front-end:
- the back-end serves information up via a JSON RESTful API
- the front-end fetches data from the back-end asynchronously via API calls
Unfortunately, this pattern is costly, requires two specialized developer profiles, and slows release cycles since you must develop and maintain two different applications (often in two different languages). It also makes rapid prototyping and SEO difficult. This pattern has been dominant since the early 2010s. It's the price that we've had to pay in order to deliver web apps with the look and feel of desktop apps. This is starting to change though, as many teams are recognizing that the gains don't outweigh the costs and are experimenting with new patterns for delivering a SPA. One pattern that's beginning to gain traction is to serve up HTML instead of JSON over a WebSocket.
How does it work?
Chris McCord, creator of Phoenix (the most popular Framework within the Elixir ecosystem), presented a technology called LiveView at ElixirConf 2019, which serves HTML over WebSockets. Shortly after, he demonstrated how to build a real-time Twitter clone in just 15 minutes with LiveView without a client-side JavaScript framework like React, Angular, or Vue. He showed that it was possible to deliver a slick, real-time UI from a back-end framework. This inspired other developers to create their own implementations using other languages and web frameworks.
McCord's solution is to send HTML to the front-end instead of JSON via WebSockets. This approach not only simplifies development, but you also get a nice performance boost as well, since the rendering logic is handled by the back-end and the front-end doesn't need to make any new HTTP requests to get new data.
Traditional approach
Again, with this approach, the browser kicks things off by making an HTTP request from the front-end to obtain a JSON response with the raw, preprocessed information. The front-end is then responsible for processing the information and creating the corresponding HTML.
HTML over WebSockets approach
With this approach, the browser or server can kick things off since WebSockets provides bi-directional communication.
Example
Let's looks at a quick example of displaying a blog article.
-
Connection: We start with a connection. WebSockets enable bi-directional communication between the client and server, which you just have to establish once.
-
Component request: The client requests the content for a particular article associated with the
/article/2
route. -
Back-end logic: The server generates the relevant HTML, CSS, and JavaScript for the template, using a templating system (like Jinja), and returns the template fragment through the WebSocket channel.
-
Update DOM: Finally, the front-end updates the DOM with the template fragment to display the blog article.
Django Demo
I created a prototype of the HTML over WebSockets approach with Django that uses Django Channels for WebSocket support. The app itself is fairly simple. It's just a blog with articles and comments. That said, it's a full SPA, so page changes don't required a page refresh.
You can see the power of WebSockets here:
You can find the code on GitHub.
Benefits and drawbacks
Benefits:
- HTML rendering / processing happens solely on the back-end
- Real-time
- The WebSockets protocol is faster than HTTP
- Works with slow connections
- Create a SPA with hardly any JavaScript
- Straightforward SEO
Drawbacks:
- Server requires more resources since you have to leave a WebSocket open per client
- Nascent ecosystem - few frameworks, tutorials, and documentation
Resources
You can start with the following resources:
- The Future of Web Software Is HTML-over-WebSockets
- Phoenix LiveView
- Hotwire - build modern web apps by sending HTML over the wire
- Reactor - a LiveView library for Django
- Sockpuppet - build reactive applications with the Django tooling you already know and love
- Action Cable - seamlessly integrate WebSockets with the rest of your Ruby and Rails app
- AnyCable - build lightning fast, reliable real-time applications with Ruby and Rails
Conclusion
While this approach is still very new, it deserves a look. Adoption is growing and more and more tools and examples are appearing every month. On a personal note, I'm surprised at how little known it seems to be. I imagine this has a lot to do with just how powerful the JavaScript ecosystem is.