Part 7 · 1 chapters · ~8 min
Phoenix and LiveView Internals
Plug and the connection struct, the endpoint and Cowboy or Bandit HTTP servers, Phoenix.PubSub and its adapters, Channels and the socket protocol, Presence with CRDTs, LiveView's lifecycle (static render, connect, mount, handle_event, handle_info), change tracking and diffs, LiveView JS hooks, and LiveView's trade-offs.
8
Real-time without a SPA
code
defmodule LedgerWeb.BalanceLive do
use LedgerWeb, :live_view
def mount(%{"id" => id}, _session, socket) do
if connected?(socket), do: Phoenix.PubSub.subscribe(Ledger.PubSub, "account:" <> id)
{:ok, assign(socket, id: id, balance: Ledger.balance(id))}
end
def handle_info({:posting_created, %{account_id: id}}, %{assigns: %{id: id}} = socket),
do: {:noreply, assign(socket, balance: Ledger.balance(id))}
def render(assigns), do: ~H"""
<p>Balance: <%= format_ngn(@balance) %></p>
"""
endPresence tracks who is online across a cluster using a CRDT (Distributed Systems, Formal Theory P6), so it converges without a central store. Bandit, a pure-Elixir HTTP server, is now the default in new Phoenix apps, replacing Cowboy.
HOW LIVEVIEW WORKS
server-rendered, stateful, real-time UI over a WebSocket
swipe the figure sideways, or tap expand for full screen
1/4
first render
The first request returns full HTML (fast first paint, SEO); the client then opens a WebSocket and a LiveView process mounts on the server.
HTML first, then socketone process per page