BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Phoenix LiveView Promises SPA-Like Interactivity for Real-Time Server-Rendered Apps

Phoenix LiveView Promises SPA-Like Interactivity for Real-Time Server-Rendered Apps

9 years after the Phoenix web framework was made generally available, Phoenix LiveView recently reached 1.0 (release candidate). LiveView allows developers to create rich, real-time server-rendered applications without writing JavaScript. LiveView relies on the Erlang virtual machine (BEAM) to scale to millions of WebSocket connections handled by multiple processes concurrently.

Chris McCord, the programmer behind the Phoenix framework, explained how LiveView came to be as follows:

I started LiveView to scratch an itch. I wanted to create dynamic server-rendered applications without writing JavaScript. I was tired of the inevitable ballooning complexity that it brings. […] We write the HTTP glue or GraphQL schemas and resolvers, then we figure out which validation logic needs shared or dup’d. It goes on and on from there – how do we get localization information to the client? What data serializers do we need? How do we wire up WebSockets and IPC back to our code? Is our JS bundle getting too large? I guess it’s time to start turning the Webpack or Parcel knobs. […] We’ve all felt this pain.

Phoenix LiveView is a member of the Phoenix ecosystem that allows programmers to write reactive web applications with little to no separate frontend codebase. LiveView leverages WebSockets rather than HTTP to maintain stateful long-lived connections between client and server. Web pages and their updates in response to user interactions are provided by the server. Client/server messages use highly scalable Phoenix Channels. The server can also use the bidirectional socket channel to communicate back to the client the interactions originating from other application users.

WebSockets typically provide lower latency than HTTP. Their persistent connection eliminates the need to repeatedly establish connections, minimizing handshakes and network overhead. WebSockets are often more efficient for real-time interactions where speed is critical. WebSockets however consume additional server resources to maintain the state of the connection.

On the other hand, HTTP requests benefit from distribution mechanisms like caching, CDN, and load balancing. Implementing stateful web applications over HTTP and REST may however require maintaining state on the client; passing pieces of state in the HTTP request, resulting in heavier payloads, thus more latency; or maintaining pieces of state in an external location for the server to retrieve it. In that paradigm, stateless servers can scale independently of the application state.

Mc Cord explains the latency advantage of LiveView as follows:

Every LiveView holds a connection to the server so page navigation happens via live navigation. TLS handshakes, current user auth, etc happen a single time for the lifetime of the user’s visit. This allows page navigation to happen via a single WebSocket frame and fewer database queries for any client action. The result is fewer round trips from the client and simply less work done by the server. This provides less latency for the end-user compared to a SPA fetching data or sending mutations up to a server.

Mc Cord claims that, despite the memory tax on the server, LiveView remains scalable enough in practice to cover applications with a large user base such as WhatsApp:

Holding a stateful connection comes at the cost of server memory, but it’s far cheaper than folks expect. At a baseline, a given channel connection consumes 40kb of memory. This gives a 1GB server a theoretical ceiling of ~25,000 concurrent LiveViews. Of course, the more state you store, the more memory you consume, but you only hold onto the state you need. We also have stream primitives for handling large collections without impacting memory. Elixir and the Erlang VM were designed for this. Scaling a stateful system to millions of concurrent users isn’t theoretical – we do it all the time. See WhatsApp, Discord, or our own benchmarks as examples.

LiveView strives to minimize the network payload to further improve latency. To do so, it uses a page templating mechanism that facilitates the identification of the minimal information to send to the client in response to user interactions; and a DOM diffing library (e.g., morphdom) to compute the subsequent minimal updates to perform on the webpage. José Valim, the creator of the Elixir programming language, presented in a blog post the technical details related to LiveView’s optimizations.

LiveView additionally includes a declarative component system dubbed HEEx. HEEx components are markup-producing functions whose dependencies (e.g., props, state, slots) are annotated. An example is as follows:

@doc """
Renders a button.

## Examples

    <.button>Send!</.button>
    <.button phx-click="go">Send!</.button>
"""
attr :type, :string, default: nil
attr :rest, :global, include: ~w(disabled form name value)

slot :inner_block, required: true

def button(assigns) do
  ~H"""
  <button
    type={@type}
    class="rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3 text-white"
    {@rest}
  >
    <%= render_slot(@inner_block) %>
  </button>
  """
end

The previous code showcases a component that accepts one custom attribute ( type), any of the standard HTML attributes (global) (e.g., class), and one slot argument. Components being functions, they are more reusable than template partials. Component slots provide an additional layer of user customization.

One Reddit user shared his enthusiasm about the new release in the following terms:

Great news! Very happy to see that it’s finally here.

I use Phoenix (with and without LiveView) every day both at my day job and on side projects, and I couldn’t be happier with it. I’m so blazingly productive in this stack; it makes webdev with anything else feel like running in quicksand.

I’m really excited to see how Elixir develops in the years ahead. It’s still relatively small, but it’s only getting bigger and I think it has a very bright future.

LiveView runs on the server with a companion JS library on the frontend. While the amount of JavaScript code that needs to be written in Phoenix web apps is vastly reduced, writing custom JavaScript is possible and in some cases necessary.

Phoenix LiveView is an open-source project distributed under the MIT license. Interested developers can review LiveView’s documentation.

About the Author

Rate this Article

Adoption
Style

BT