LiveView keeps you warm!
�aka: why you should consider LiveView for your next Web project�
Arjan Scherpenisse
�Erlang, Elixir & Friends Devroom, FOSDEM'23
Agenda
Background
About me
Programming since I was a kid, first OTP R13B01
Scientific background with a hands-on attitude
Interested in AI, hardware/software interaction, art…
About this art stuff:
Working together with Klasien van de Zandschulp for several projects
“It is like a printer, but for yarn”
(famous last words)
Learning to knit
Learned to operate the machine after several weeks
Knitted several garments (hats mostly)
Sourcing the proper yarn is hard, process error-prone
This is me knitting
Automating the knitting
Found Hackspace Bamberg which already had hacked a Passap machine
Used same schematic for arduino to control the knitting
Old UI
The UI am I replacing:
New UI
Knitting machine software diagram
Arduino
LiveKnit.Serial
LiveKnit.Control
%LiveKnit.Machine.Passap{}
USB
Phoenix �PubSub
GenServer�state
LiveKnit.SerialMonitor
LiveKnitWeb.Live.Main
Phoenix �PubSub
Browser
HTML�WebSocket
Here is where the LiveView magic happens :-)
Hardware
Elixir / OTP
Browser
Nerves.UART
What is LiveView?
“LiveView provides rich, real-time user experiences with server-rendered HTML.”
A little bit of �web history
First there was the “static HTML” web (1991)
Browser
index.html
HTML
The PHP / DHTML wave (~2000)
Browser
index.php
HTML
Everything was rendered on the server
Javascript was added for small bits of interactivity
Server state managed with sessions/cookies
logic
logic
Javascript Wave (from ~2008)
More logic on the client, separation of backend and frontend developers
Culminating in the rise of the SPA (Single Page Application), React, …
Browser
<html>
HTML
REST / GraphQL
“Ajax”
logic
logic
Phoenix LiveView (from 2018)
Browser
LiveView
HTML�WebSocket
A mix of client and server development like in the Old Days™, no need to write anymore Javascript! (unless you really want to)
logic
So how does it actually work?
Glad you asked…
1 liveview process per page, that contains all state,
Templates are rendered on server
DOM diffs are sent to client
Events are sent back to server
Browser
LiveView process (connected)
DOM diffs
state
LiveView render (not connected)
Browser
HTML
WebSocket (Phoenix Channel) is established…
Events
And this is what that looks like:
Liveview hello world
▶ mix phx.new live_demo --no-ecto --no-gettext --no-dashboard --no-mailer
Let’s make the knitting live :-)
LiveView is live & reactive
handle_event callback lets you react to events from the browser
handle_info callback lets you react to events from other parts of the application
(for instance with Phoenix PubSub)
LiveKnitWeb.Live.Main
Let’s look at the knitting machine code
* disclaimer!
Patterns of reusability
Patterns of reusability
Let’s view the LiveKnit components
These are all components
Function components
LiveComponent (stateful)
LiveComponent
�<live_component id="LC1" module={MyComponent} />
Browser
LiveView process (connected)
DOM diffs
Gathered for all components
LiveView state
Addressed events�(phx-target)
LC2 state
LC1 state
…
render
Slots and attrs
Other component options
Javascript integration
Javascript integration
…Because sometimes, you must.
LiveView Javascript hooks
Browser
LiveView process (connected)
push_event(“...”, payload)
LiveView state
this.pushEvent(...)
Hook JS
Hook state
LiveKnit analyze page demo
LiveView “cons”
<button type="submit" phx-disable-with="Saving...">Save</button>
The Future
LiveView competitors
Any popular tech gets cloned into other programming languages:
https://github.com/liveviews/liveviews
Rise of WASM causes other languages to be used in the browser
LiveView native
Native wrapper
iOS / Android
LiveView process
“UI view tree” diffs
state
Events
LV bridge library
Mobile client
Server
LiveView native
Native wrapper
iOS / Android
Linked BEAM / Lumen
LiveView process
state
LV bridge library
Or even…!
Thanks for listening!
…any questions?
Find me:�genserver.social/arjan
Bonus: The “Pat” DSL
font = Font.load(:sigi5b, fg: "X", bg: " ", stride: 1)
string = "hello there"
{w, h} = Font.measure(font, string)
target = Pat.new(w, h, " ")
target = Font.render(font, target, string, 0, 0)
Pat.print(target)