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.8.8 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:

Where Next?

Popular in Phoenix News Top

steffend
LiveView 1.2.0 is out now! Colocated CSS The biggest new feature is support for Colocated CSS, which is built on the work we did in 1.1 ...
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
A minor vulnerability has been disclosed for applications redirecting to URLs provided by user input. Only applications passing user inpu...
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
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 31194 112
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
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
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
Hey folks, Phoenix 1.3.0 is out! The final release please brings tweaks to web directory and alias conventions that were estabished in t...
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

Other popular topics Top

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43806 214
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement