Phoenix 1.7.2 发布

发布于 2023 年 3 月 20 日,作者 Chris McCord


Phoenix 1.7.2 发布了!这个小版本更新包含了一些值得讨论的功能。让我们开始吧!

更轻松的 Tailwind 禁用

Phoenix 1.7 默认包含 tailwindcss 以及一个新的基于组件的表单架构。这使得禁用 Tailwind 并使用其他工具或自定义 CSS 变得非常容易,但仍然需要一些手动步骤。也就是说,你需要删除 tailwind.config.js 文件和开发 :watchers 配置。我们引入了一个 mix phx.new --no-tailwind 标志,让用户在生成新项目时跳过这些步骤。

通道和 LiveView 套接字排水

对于像通道或 LiveView 这样的有状态应用,大规模冷部署可能难以协调。部署通常需要自定义调整你的部署工具或代理,以缓慢地推出发布,以避免因大量流量涌入新服务器而导致的服务器过载。Phoenix 1.7.2 引入了一个新的通道套接字排水功能,它会在应用程序关闭时协调一个分批、分阶段的排水过程。排水默认启用,你可以在端点的 socket 宏中配置关闭。

来自文档

  @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.
  """

如果你没有在大规模运行,你无需担心此功能,但它会在你需要时等待着你。如果你已经在进行大规模运行,此功能应该会使你的基础设施上的部署压力减轻,或者让你摆脱特定于云的配置。

JS.exec

我们引入了一个新的 JS 命令,用于在位于另一个 DOM 元素上的页面上执行现有命令。在某些情况下,这极大地优化了有效负载,否则将需要在 DOM 中多次重复相同的命令。例如,你 core_components.ex 模块中的默认模态之前包含多个地方的重复命令,用于关闭模态

  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

我们对 phx-window-keydownphx-click-away 有相同的命令,以及 phx-remove 上的类似命令。这些命令在 ESC 键按下以及单击模态外部时都会隐藏模态并调用调用者的命令,并在用户导航离开时过渡模态。当 JS 命令包含诸如过渡之类的内容及其自己的类和计时值时,这会导致相当大的有效负载。通过仅指定一次命令并告诉 LiveView 它可以在哪里执行它,我们可以将有效负载减少一半以上。新的模态看起来像这样

  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

我们使用 JS.execdata-cancel 属性中执行 hide_modal 命令,该命令在 phx-remove 中指定。我们拥有与之前相同的行为,但现在只发送一次,而不是三次。

快乐编码!

–Chris