I’m pleased to announce the first release candidate of Phoenix 1.6.0 has landed on the heels of a fresh LiveView 0.16 release! This release brings a number of major additions, quality of life improvements, bug fixes, and a couple deprecations. You can grab the rc phx.new
generator with the following command:
$ mix archive.install hex phx_new 1.6.0-rc.0
New authentication and mailer generators
Thanks to efforts by José Valim and Aaron Renner, Phoenix 1.6 ships with a new phx.gen.auth
command for a complete authentication solution bootstrapped into your application. You can read about the design decisions behind the authentication generators in José’s post on the Dashbit blog. Phoenix also now includes swoosh by default for mailer support and a new phx.gen.notifier
task for generating a notifier for sending email along with a dev mailbox for local development.
New LiveView HEEx engine
In addition to the generators, Phoenix LiveView 0.16 was just released with a new HTML engine (HEEx, ~H
) for HTML-aware template compilation which you’ll see utilized in all phoenix generated HTML files going forward (phx.new, phx.gen.html, phx.gen.live, etc
). The new engine not only enforces proper HTML, but provides syntax conveniences for rendering components, such as <.form for={@user} id="user-form">
. This new engine is thanks to Marlus Saraiva’s excellent work that he extracted from his wonderful Surface library, which builds features on top of Phoenix LiveView. We look forward to seeing where each project can continue to innovate and share back as we work towards new engine features. With the HTML engine and function components in place, we have the layed the groundwork for a vibrant ecosystem of shared and resuable components. You can follow along the HEEx roadmap to stay up to date on our feature plans. For now, here’s a quick rundown on HEEx from the Phoenix LiveView docs to bring folks up to speed:
Note:
HEEx
requires Elixir >=1.12.0
in order to provide accurate
file:line:column information in error messages. Earlier Elixir versions will
work but will show inaccurate error messages.
HEEx
is a HTML-aware and component-friendly extension of EEx
that provides:
- Built-in handling of HTML attributes
- An HTML-like notation for injecting function components
- Compile-time validation of the structure of the template
- The ability to minimize the amount of data sent over the wire
Example
~H"""
<div title="My div" class={@class}>
<p>Hello <%= @name %></p>
<MyApp.Weather.city name="Kraków"/>
</div>
"""
Syntax
HEEx
is built on top of Embedded Elixir (EEx
), a templating syntax that uses
<%= ... %>
for interpolating results. In this section, we are going to cover the
basic constructs in HEEx
templates as well as its syntax extensions.
Interpolation
Both HEEx
and EEx
templates use <%= ... %>
for interpolating code inside the body
of HTML tags:
<p>Hello, <%= @name %></p>
Similarly, conditionals and other block Elixir constructs are supported:
<%= if @show_greeting? do %>
<p>Hello, <%= @name %></p>
<% end %>
Note we don’t include the equal sign =
in the closing tag (because the closing
tag does not output anything).
There is one important difference between HEEx
and Elixir’s builtin EEx
.
HEEx
uses a specific annotation for interpolating HTML tags and attributes.
Let’s check it out.
HEEx extension: Defining attributes
Since HEEx
must parse and validate the HTML structure, code interpolation using
<%= ... %>
and <% ... %>
are restricted to the body (inner content) of the
HTML/component nodes and it cannot be applied within tags.
For instance, the following syntax is invalid:
<div class="<%= @class %>">
...
</div>
Instead do:
<div class={@class}>
...
</div>
For multiple dynamic attributes, you can use the same notation but without
assigning the expression to any specific attribute.
<div {@dynamic_attrs}>
...
</div>
The expression inside { ... }
must be either a keyword list or a map containing
the key-value pairs representing the dynamic attributes.
HEEx extension: Defining function components
Function components are stateless components implemented as pure functions
with the help of the Phoenix.Component
module. They can be either local
(same module) or remote (external module).
HEEx
allows invoking whose function components directly in the template
using an HTML-like notation. For example, a remote function:
<MyApp.Weather.city name="Kraków"/>
A local function can be invoked with a leading dot:
<.city name="Kraków"/>
where the component could be defined as follows:
defmodule MyApp.Weather do
use Phoenix.Component
def city(assigns) do
~H"""
The chosen city is: <%= @city %>.
"""
end
def country(assigns) do
~H"""
The chosen country is: <%= @country %>.
"""
end
end
It is typically best to group related functions into a single module, as
opposed to having many modules with a single render/1
function. You can
learn more about components in Phoenix.Component
.
New LiveView server lifecycle hooks
Thanks to work by Michael Crumm on the Phoenix team, LiveView 0.16 introduces on_mount
and attach_hook
hooks which provide a mechanism to tap into key stages of the LiveView lifecycle. This allows developers to bind/update assigns, intercept events, patches, and regular messages when necessary, and to inject common functionality. Hooks may be attached to any of the following lifecycle stages: :mount
(via on_mount/1
), :handle_params
, :handle_event
, and :handle_info
.
New LiveView live_session
for optimized navigation
LiveView 0.16 also introduces the live_session
macro in the router to group live routes together. This allows all live navigation through live redirects to happen over the existing websocket connection. This avoids an extra HTTP round trip to the server and provides an extremely fast navigation experience because an HTTP handshake is no longer necessary at all. The live_session
also allows a life-cycle on_mount
hook to be provided, allowing LiveViews to share common code paths such as authentication without needing to specificy the hooks on every module.
Node and webpack free asset building with esbuild
In addition to the new HTML engine, we’ve also had a major change on the way the phx.new
project generators handles assets. We have dropped webpack and node entirely from the equation. You can now build your js and css bundles without having node or npm on your system! The biggest support issues for Phoenix over the years has revolved around node tooling, breaking changes, and often times unnecessary churn. By using esbuild, projects can utilize a portable binary for multiplatform, dependency-free asset building that is fast and Just Works/tm. Five years from now you shouldn’t been afraid to make some changes to a js or css file and find your tooling has broken underneath you. Advanced front-end users can continue to take advantage of the webpack tooling that suits their work-flows, but we hope this dependency-free solution brings more “peace of mind” around assets, per the Phoenix tagline :). Big thanks to Brian Cardarella of DockYard and Max Veytsman on the Phoenix team for spelunking through our js options and experimenting with solutions, along with Wojtek Mach for heading up the portable binary esbuild extraction. Also shout out to José for writing some go and JavaScript PRs for various tools to handle mix shutdown without zombie processes.
This release also extracts Phoenix.View
into its own library phoenix_view
, so non-web users can make use of Phoenix’s view rendering without bringing in all of Phoenix.
As always, step-by-step upgrade guides can be found here.
You can also view the full changelog for more details.
Find us on elixir slack or the forums if you need help. Happy coding!
–Chris