DEV Community

Jackline Kaunda
Jackline Kaunda

Posted on

👩‍💻 Phoenix LiveView: Bringing Real-Time Magic to the Web

A Blog Post Based on the ElixirKenya Webinar #001 by Jackline Kaunda

Introduction

Phoenix LiveView has been around for some time, but it was officially announced last year (2019) by Chris McCord. Many of us have already used it to do amazing stuff, moving much of our client-side work, which we initially used to do in GitHub versions, into a finalized, published dependency.


What is Phoenix LiveView?

Phoenix LiveView is a powerful library that provides rich, real-time user experiences with server-rendered HTML.

For a long time, building rich, real-time interfaces meant relying heavily on JavaScript frameworks like React, Angular, or Vue.js. These are majorly client-side architectures. However, LiveView proposes that it might be wiser and simpler to handle this on the server side.

Here are the key takeaways:

  • Server-Side State: LiveView is stateful in the server. This is the core difference.
  • Bi-directional Communication: It achieves interactivity using WebSockets for bi-directional communication between the client and the server.
  • Minimal JavaScript: As Chris McCord said, LiveView enables you to write your UI code without really having to write JavaScript code. While the framework is built on top of JavaScript (for managing the WebSocket connection and DOM updates), the JavaScript you, the application developer, write is minimal.

This means you, as an Elixir developer, do not have to learn all the current trending JavaScript frameworks. Instead, you just have to focus on your Elixir code to make good, real-time applications, maximizing your time and resources.


🧱 The Pillars of LiveView

LiveView is built on three core systems that were already part of the Phoenix Framework:

1. Phoenix Channels

Channels have been a foundational system since the beginning of Phoenix. They use WebSockets to ensure bi-directional communication between the client (like a browser) and the server.

A key challenge that channels help solve is connection density. The beauty of Channels is that they leverage the BEAM (Erlang VM) to allow so many connections on the same node without the application crashing. This makes real-time communication robust and scalable.

2. LiveView Templates (LEx)

LiveView uses the LEx (Live EEx) template engine, which was created to achieve two main goals:

  1. Initial Rendering: To render the template initially.
  2. Diff Tracking: To track differences in the content of an HTML page.

When LEx renders your template to the browser, it splits the resulting HTML into two parts:

  • Static Part: Content that will never change (e.g., HTML tags).
  • Dynamic Part: Content that changes with time (e.g., a variable assigned to a time value).

This split is essential for efficient updates. LEx calculates the minimal difference—the "diff"—between the old and new dynamic content, optimizing the payload sent over the WebSocket.

3. JavaScript

While we write minimal JS, a file called phoenix_live_view.js contains all the necessary scripts for LiveView to manage the connection and attain the rich user experience. It plays a major part in handling the client-server communication.


🚀 The LiveView Lifecycle: From Stateless to Stateful

The life cycle of a LiveView begins with a two-step process:

1. Initial Stateless HTTP Request (Mount to the DOM)

When you first load a LiveView page (e.g., navigating to /messenger):

  • A GET request is sent to the server.
  • The server calls the mount function, which gets all the data needed (e.g., from a database or API) and puts it into the assigns of the socket.
  • The data is passed to the render function, which sends back a full HTML response to the client.

This first step ensures a fast, SEO-friendly initial page load.

2. Stateful WebSocket Connection

After the HTML is rendered:

  • The client uses a small piece of JavaScript code to connect to the server via a WebSocket.
  • The server then spawns a new Phoenix LiveView Process for that connection.
  • This process calls the mount function again (this time, the stateful version), gets the data, and passes it to the render function.

From this point on, the connection is stateful.

How Updates Happen

When an event is triggered (a click, a keypress, etc.):

  1. The message is sent over the WebSocket to the LiveView process.
  2. The server calls the appropriate handle_event callback.
  3. The server updates the socket assigns (@changes).
  4. The server renders the new template and calculates the minimal diff (using LEx).
  5. This small patch is sent back to the client.
  6. The client uses morphdom.js (a lightweight library) to patch the existing DOM, not a virtual DOM.

This is how LiveView maintains its own state throughout the session and updates the UI in real-time efficiently.


Demo: A Real-Time To-Do Application

In a short demo, we saw a simple to-do application built with LiveView. The power was immediately visible:

When typing in a new to-do item, the list of to-dos updated immediately below the input field, demonstrating the real-time feedback loop.

By inspecting the WebSocket traffic, we saw the transparency of LiveView:

  • The event was triggered.
  • The message included the topic (lv:*subtopic*) and the actual content typed.
  • The server sent back an updated render event, complete with the list of to-dos updated in the socket assigns.

This shows that with very few lines of code, you can achieve powerful, real-time interactivity.


Conclusion

Phoenix LiveView is a game-changer. It enables Elixir developers to build highly interactive, real-time web applications without the overhead and complexity of traditional client-side frameworks. By leveraging Channels, LEx, and the power of the BEAM, LiveView offers an incredibly efficient and developer-friendly path to modern web development.

Top comments (0)