chrismccord

chrismccord

Creator of Phoenix

Phoenix 1.7.2 released

Announcement post dup’d here for convenience:


Phoenix 1.7.2 is out! This minor release includes a couple features worth talking about. Let’s get to it!

Easier Tailwind opt-out

Phoenix 1.7 included tailwindcss by default along with a new form component-based architecture. This makes it super easy to opt-out of Tailwind in favor for another tool or custom CSS, but there were still a few manual steps. Namely, you needed to remove the tailwind.config.js file and the dev :watchers configuration. We introduced a mix phx.new --no-tailwind flag to let folks skip these steps when generating a new project.

Channel and LiveView Socket Draining

Cold deploys at high scale for stateful apps like channels or LiveView can be challenging to orchestrate. Deploys often involve custom tuning your deploy tools or proxies to roll out the release slowly to avoid overloading the new servers with a thundering herd of traffic. Phoenix 1.7.2 introduces a new channel socket drain feature, which orchestrates a batched, staged drain process on application shutdown. Draining is enabled by default and you can configure the shutdown from the socket macro in your endpoint.

From the docs:

  @doc """
  ...
  * `:drainer` - a keyword list configuring how to drain sockets
    on application shutdown. The goal is to notify all channels (and
    LiveViews) clients to reconnect. The supported options are:

    * `:batch_size` - How many clients to notify at once in a given batch.
      Defaults to 10000.
    * `:batch_interval` - The amount of time in milliseconds given for a
      batch to terminate. Defaults to 2000ms.
    * `:shutdown` - The maximum amount of time in milliseconds allowed
      to drain all batches. Defaults to 30000ms.

  For example, if you have 150k connections, the default values will
  split them into 15 batches of 10k connections. Each batch takes
  2000ms before the next batch starts. In this case, we will do everything
  right under the maximum shutdown time of 30000ms. Therefore, as
  you increase the number of connections, remember to adjust the shutdown
  accordingly. Finally, after the socket drainer runs, the lower level
  HTTP/HTTPS connection drainer will still run, and apply to all connections.
  Set it to `false` to disable draining.
  """

If you’re not operating at high scale, you don’t need to to worry about this feature, but it will be there and waiting when you need it. If you’re already operating at high scale, this feature should make deploys less stressful on your infrastructure or allow you to ditch cloud-specific configuration.

JS.exec

We introduced a new JS command for executing an existing command on the page located on another DOM element. This greatly optimizes payloads in certain cases that otherwise involved shoving the same duplicated command in the DOM multiple times. For example, the default modal in your core_components.ex module previously contained a duplicated command for closing the modal in multiple places:

  def modal(assigns) do
    ~H"""
    <div
      id={@id}
      phx-mounted={@show && show_modal(@id)}
      phx-remove={hide_modal(@id)}
    >
      <div id={"#{@id}-bg"}>
      <div>
        <div class="flex min-h-full items-center justify-center">
          <div class="w-full max-w-3xl p-4 sm:p-6 lg:py-8">
            <.focus_wrap
              id={"#{@id}-container"}
              phx-window-keydown={hide_modal(@on_cancel, @id)}
              phx-key="escape"
              phx-click-away={hide_modal(@on_cancel, @id)}
    """
  end

We had the same command for phx-window-keydown and phx-click-away, and a similar command on phx-remove. These hide the modal and invoke the caller’s own command both on ESC and when clicking outside the modal, and transition the modal when the user navigates away. This produces a sizable payload when the JS commands contain things like transitions with their own classes and timing values. We can cut the payload by more than half by specifying the command only once and telling LiveView where it can execute it. The new modal looks like this:

  def modal(assigns) do
    ~H"""
    <div
      id={@id}
      phx-mounted={@show && show_modal(@id)}
      phx-remove={hide_modal(@id)}
      data-cancel={JS.exec(@on_cancel, "phx-remove")}
    >
      <div id={"#{@id}-bg"}>
      <div>
        <div class="flex min-h-full items-center justify-center">
          <div class="w-full max-w-3xl p-4 sm:p-6 lg:py-8">
            <.focus_wrap
              id={"#{@id}-container"}
              phx-window-keydown={JS.exec("data-cancel", to: "##{@id}")}
              phx-key="escape"
              phx-click-away={JS.exec("data-cancel", to: "##{@id}")}
    """
  end

We use JS.exec to execute the data-cancel attribute where we share the hide_modal command specified in phx-remove. We have the same behavior as before, but now it’s only sent a single time, instead of three times.

Happy coding!

–Chris

Most Liked

josevalim

josevalim

Creator of Elixir

@shahryarjb doing so is not really encouraged because if the content was rendered by the server, the next time the server renders, it will add the same contents back.

You can only do so if you are inside phx-update="ignore", which is also a construct you should avoid, so our recommendation is to either hide the element using the existing helpers or rely on JavaScript if you really want to remove it.

codeanpeace

codeanpeace

There’s the handy PhoenixDiff · v1.7.1 to v1.7.2 to show exactly what’s changed between two given versions of a newly generated phoenix app.

It’s also worth running mix local.phx — Phoenix v1.7.2 to update the Phoenix project generator locally, especially before creating any new apps.

aiwaiwa

aiwaiwa

Chris, Jose and all! Thank you so much for the release! Exciting times!

Quick question: How far are you from implementing emptying a stream? I’m postponing my filtering & sorting until there’s a first-class support for it :smiley:

muelthe

muelthe

Thank you!

soup

soup

Check the changelog for anything that might explode on you then mix deps.update phoenix. You may have to fiddle with mix.exs if your version constraint is restrictive.

Where Next?

Popular in Phoenix News Top

chrismccord
LiveView 1.0.0-rc.0 is out! This 1.0 milestone comes almost six years after the first LiveView commit. I published a Phoenix blog highli...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
New
chrismccord
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 relea...
New
josevalim
We were notified by Panagiotis Nezis that certain payloads could take a long time to process when converted to integers. New Erlang/OTP v...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
chrismccord
The final release of Phoenix 1.7 is out! Most of the new features have been outlined in the 1.7 RC thread, but it has been a few months s...
New
chrismccord
Announcement post dup’d here for convenience: Phoenix 1.7.2 is out! This minor release includes a couple features worth talking about. ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
chrismccord
Check the announcement blog for details! Blog duped here for convenience: Phoenix 1.8.0-rc released! The first release candidate of P...
414 11568 167
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement