Skip to content

Instantly share code, notes, and snippets.

@chrismccord
Last active February 24, 2024 13:56
Show Gist options
  • Star 64 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save chrismccord/2ab350f154235ad4a4d0f4de6decba7b to your computer and use it in GitHub Desktop.
Save chrismccord/2ab350f154235ad4a4d0f4de6decba7b to your computer and use it in GitHub Desktop.

Phoenix 1.5.x to 1.6 upgrade instructions

Update your deps

In mix.exs, update your phoenix, phoenix_html, telemetry_metrics, telemetry_poller and phoenix_live_dashboard deps, and add phoenix_live_view:

def deps do
    [
      {:phoenix, "~> 1.6.0"},
      ...
      {:phoenix_html, "~> 3.0"},
      {:phoenix_live_view, "~> 0.16.4"},
      {:phoenix_live_dashboard, "~> 0.5"},
      {:telemetry_metrics, "~> 0.6"},
      {:telemetry_poller, "~> 0.5"},
      ...
    ]
end

Next, run mix deps.get to grab your new deps.

Rename your .html.eex and .html.leex templates to .html.heex (optional)

While leex templates have been deprecated, this step is optional. For the most part, existing templates should continue to work, but the HTML-aware HEEx engine will enforce valid markup and is more strict in the elixir expressions that appear within an open and closing tag. For example, the following code will raise:

<div id="<%= @id %>">

Instead of the standard <%= %> EEx expressions, elixir expressions inside tags can only appear withing {}, such as:

<div id={@id}>

<%= %> expressions remain valid outside of HTML tags in the EEx engine.

To update your existing templates, rename all your .html.eex and .html.leex templats to .html.heex and follow the parser errors to find any tags that require the new {} attribute form.

Also be sure to review the HEEx documentation for more information on features.

Migrate to esbuild for js and css bundling (optional)

Phoenix's watchers configuration is build-tool agnostic, so you may continue to enjoy your existing webpack configurations generated by phoenix 1.5 or earlier. If only have basic js and css needs and you would like to take advantage of our new esbuild usage, for a dependency-free asset builder powered by a portably binary, follow these steps:

First delete your webpack config and related node files:

$ rm assets/webpack.config.js assets/package.json assets/package-lock.json assets/.babelrc
$ rm -rf assetes/node_modules

Next, add the esbuild mix dep to your mix.exs deps:

def deps do
  [
    ...
    {:esbuild, "~> 0.2", runtime: Mix.env() == :dev},
  ]
end

Next, configure esbuild in config/config.exs:

# Configure esbuild (the version is required)
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__)}
  ]

Next, replace the node watcher with esbuild in your endpoint watcher config in config/dev.exs:

config :demo, DemoWeb.Endpoint,
  ...,
  watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
  ]

Next, add a new assets.deploy mix alias in your mix.exs for easy asset building:

  defp aliases do
    [
      ...,
      "assets.deploy": ["esbuild default --minify", "phx.digest"]
    ]
  end

Running $ mix assets.deploy will download the esbuild binary on first run and then build your assets:

$ mix assets.deploy
21:40:37.588 [debug] Downloading esbuild from https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.12.18.tgz

  ../priv/static/assets/app.css  9.7kb
  ../priv/static/assets/app.js   1.3kb

⚡ Done in 12ms
Check your digested files at "priv/static"

Next, update your layouts, such as app.html.heex or root.html.heex to use the new assets prefix instead of js/app.js and css/app.css:

    <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>

Finally, update your Plug.Static :only options in your lib/app_web/endpoint.ex to be aware of the new assets directory:

  plug Plug.Static,
    at: "/",
    from: :my_app,
    gzip: false,
    only: ~w(assets fonts images favicon.ico robots.txt)
@arfl
Copy link

arfl commented Feb 2, 2022

@florish
Copy link

florish commented Feb 2, 2022

@arfl Hey that's even better! For my understanding: apart from the layout, the diff content is the same as for the link I posted, isn't it?

@arfl
Copy link

arfl commented Feb 3, 2022

@florish I do not know exactly, but the source code is on github (link to github repo in the right upper corner of the app). Seems that they just generate two versions of the app using the --live option and call this code to generate the diff.

@pinksynth
Copy link

Very helpful! Noticed a typo: assetes instead of assets:

rm -rf assetes/node_modules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment