Phoenix’s live reload functionality instantly refreshes your browser when you update a file in your code editor. The experience is beautiful in its simplicity and the Phoenix code that does it is remarkably lightweight as well.
Let’s walk through the elegant magic of LiveReload.
When you runmix phoenix.new
to generate a Phoenix app, you’ll see the following in web/endpoint.ex:
if code_reloading? dosocket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socketplug Phoenix.LiveReloader...end
Phoenix.LiveReloader
is responsible for injecting the required HTML bits that trigger live reloading. This is a module plug: it transforms the connection by implementing call/2
.
Phoenix.LiveReloader
actually declares two call/2
functions:
def call(conn, _) do
This injects an iframe into the HTML that will load “/phoenix/live_reload_iframe”.
2. The other **call/2**
function definition loads the iframe content by pattern matching against the request path (source):
def call(%Plug.Conn{path_info: ["phoenix", "live_reload", "frame"]} = conn , _) do
This returns HTML that injects the client-side Javascript to connect to the Phoenix.LiveReloader.Socket
.
The [fs](https://github.com/synrc/fs)
Erlang package is used to listen to changes to files. When the javascript in the iframe joins the channel, LiveReloader
begins subscribing to file system changes (source).
By default, your static assets (javascript, css, etc) and web views and templates.
Have you deployed a Phoenix app? Try Scout, a new Elixir app monitoring solution I helped develop. Signup is free.
After :fs.subscribe/0
is called, the channel process listens for fs
message events by defining handle_info/
(source):
def handle_info({_pid, {:fs, :file_event}, {path, _event}}, socket) do
This receives all file events on the filesystem. Since we only care about a subset, matches_any_pattern?/2
checks to see if the file is within our Phoenix app.
Then, we send a message via the channel notifying of the change:
push socket, "assets_change", %{asset_type: asset_type}
The JS listens for the assets_change
event and updates the window in one of two ways:
LiveReload weaves an interesting path through your app: inserting a plug to inject content into the HTML, rendering an iframe, inserting Javascript into the iframe and subscribing to a channel, listening for filesystem events, sending messages via the channel on relevant events, and finally, reloading your browser window.