Subscribe to access all episodes. View plans →
Published October 19, 2021
Chris McCord’s upgrade guide
Phoenix 1.6 was released including many new great features like new authentication and mail generators, webpack free asset building with esbuild, and the new LiveView HEEx engine. In this episode let’s update an existing Phoenix 1.5 application to 1.6. To do this we’ll be working from Chris McCord’s upgrade guide here.
Alright, let’s get started. The first thing we’ll want to do is open our Mixfile and we’ll need to bump the versions of a few dependencies. We’ll update phoenix
to 1.6, phoenix_live_view
to 0.16.4, phoenix_html
to 3.0, phoenix_live_dashboard
to 0.5, telemetry_metrics
to 0.6, and telemetry_poller
to 0.5. Then let’s include esbuild
to use the new way to build assets.
mix.exs
defmodule Teacher.MixProject do
...
defp deps do
...
{:phoenix, "~> 1.6"},
{:phoenix_live_view, "~> 0.16.4"},
{:phoenix_html, "~> 3.0"},
{:phoenix_live_dashboard, "~> 0.5"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 0.5"},
{:esbuild, "~> 0.2", runtime: Mix.env() == :dev},
...
end
end
With those updates let’s go to the command line and download our new dependencies with mix deps.get
.
$ mix deps.get
...
Upgraded:
phoenix 1.5.13 => 1.6.0
phoenix_html 2.14.3 => 3.0.4 (major)
phoenix_live_dashboard 0.4.0 => 0.5.3 (minor)
phoenix_live_view 0.15.1 => 0.16.4 (minor)
telemetry_metrics 0.6.0 => 0.6.1
New:
castore 0.1.12
esbuild 0.3.2
phoenix_view 1.0.0
Now with our new version of Phoenix LiveView we get the new HEEx templating language, which enforces proper HTML and provides conveniences for rendering components, which we’ll look at later. To use use the new .heex
templates we’ll rename both .html.eex
and .html.leex
templates in our application to .html.heex
. This step is optional and HEEx requires you to be running at least Elixir 1.12. Let’s check out version of Elixir great we’re using 1.12.3.
Now we just need to go through and update our templates to use the new .heex
extension. I’ll update the form_component.html
template here and to save time I’ll rename the other templates off-camera. Alright, all of the templates have been renamed to .html.heex
. So now we can go to the command line and start our server.
$ mix phx.server
...
When we do we get a compilation error in lib/teacher_web/live/album_live/index.html.heex
. At this stage we’ll need to follow the errors in our different templates and get them to work as .heex
templates. So let’s open that index.html.heex
template. And here we’re rendering the album.id
in this HTML tag. But with .heex
templates we can no longer use this syntax for interpolating Elixir code within HTML tags. Instead we’ll update this to wrap our code in {...}
.
Template path: lib/teacher_web/live/album_live/index.html.heex
...
<tr id="album-{album.id}">
...
Then let’s try to start our server again and we get another error, this time in our form_component.html.heex
. Let’s open that.
Our form needs to be updated. Phoenix LiveView provides a function component named form
which we can invoke with a leading dot. Then let’s re-write the rest of our form.
Template path: lib/teacher_web/live/album_live/form_component.html.heex
...
<.form
let={f}
for={@changeset}
id="album-form"
phx-target={@myself}
phx-change="validate"
phx-submit: "save">
<%= label f, :artist %>
<%= text_input f, :artist %>
<%= error_tag f, :artist %>
<%= label f, :title %>
<%= text_input f, :title %>
<%= error_tag f, :title %>
<%= label f, :summary %>
<%= textarea f, :summary %>
<%= error_tag f, :summary %>
<%= label f, :year %>
<%= number_input f, :year %>
<%= error_tag f, :year %>
<%= submit "Save", phx_disable_with: "Saving..." %>
</.form>
...
With our form updated, let’s try to restart our server again. When we do we get an error in the root.html.heex
so let’s open that, and we just need to update the asset paths to use the new {...}
syntax.
Template path: lib/teacher_web/templates/layout/root.html.heex
...
<link rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")}/>
<script defer type="text/javascript" src={Routes.static_path(@conn, "/js/app.js")}></script>
...
Now when we go back to the command line and start our server we don’t get any more compilation errors, but we do a warning that our esbuild version is not configured. Let’s do that now. Let’s go ahead and remove our webpack config and node files.
$ rm assets/webpack.config.js assets/package.json assets/package-lock.json assets/.babelrc
$ rm -rf assets/node_modules
Then let’s open our config.exs
and I’ll paste in the esbuild
config.
config/config.exs
...
config :esbuild,
version: "0.12.18",
default: [
args: ~w(js/app.js --bundle --target=es2016 --outdir=../priv/static/assets),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
...
Then let’s open dev.exs
config and in the config for our Endpoint
we’ll update the watchers
section to remove node and replace it with esbuild
.
config/dev.exs
...
config :teacher, TeacherWeb.Endpoint,
...
watchers: [
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
]
...
Now let’s go back to our Mixfile and add a new assets.deploy
mix task we can use to compile and serve assets in production.
mix.exs
...
defp aliases do
[
...
"assets.deploy": ["esbuild default --minify", "phx.digest"]
]
end
...
Then we need to update our CSS and JavaScript to use the new assets
prefix, so we’ll go back to the root.html.heex
template and update it to use assets
.
Template path: lib/teacher_web/templates/layout/root.html.heex
...
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
...
Now we have one more step. Let’s open the endpoint.ex
module. And update our Plug.Static
to use the new assets
directory. And we can remove the css
and js
directories since we won’t need them.
lib/teacher_web/endpoint.ex
defmodule TeacherWeb.Endpoint do
...
plug Plug.Static,
at: "/",
from: :teacher,
gzip: false,
only: ~w(assets fonts images favicon.ico robots.txt)
...
end
Let’s start the server. And great everything starts up without any errors or warnings.
$ mix phx.server
...
And if we go back to the browser and everything looks great. Our app seems to be working. But if we go to add an album, it looks like we get an error: “LiveView expects stateful components to have a single static HTML tag at the root”. This is a change we’ll have to potentially make to any stateful components we have, but fortunately we just have one in this app.
We’ll open our form_component.html.heex
. And we can see there’s not a single HTML tag at the root, so let’s update that.
Template path: lib/teacher_web/live/album_live/form_component.html.heex
<div>
...
</div>
Now if we go back to the browser - great our page is working. Our app is now upgraded to use Phoenix 1.6.