Phoenix (Elixir)MiddleTechnical

Что такое Phoenix LiveView и какую проблему он решает?

Phoenix LiveView позволяет строить интерактивный UI без JS: сервер хранит состояние, при событиях отправляет только HTML-diff через WebSocket, а браузер применяет его к DOM. Первый рендер — стандартный HTTP, последующие обновления — через WebSocket.

Phoenix LiveView: концепция и решаемая проблема

Phoenix LiveView — библиотека для построения интерактивных веб-интерфейсов без написания JavaScript. Она позволяет создавать real-time UI, формы с живой валидацией, автодополнение и другие интерактивные элементы, используя только Elixir на сервере.

Проблема, которую решает LiveView

Традиционно есть два подхода к интерактивности:

  • Server-side rendering (SSR): простой, но требует полного перезапроса страницы для каждого действия.
  • SPA (React/Vue): интерактивен, но требует REST/GraphQL API, клиентского state-менеджмента, бандлинга и значительного объёма JS-кода.

LiveView предлагает третий путь: серверный рендеринг с WebSocket-синхронизацией состояния. Сервер владеет состоянием, а браузер отображает только diff.

Как работает LiveView

  1. Первый запрос — обычный HTTP, сервер рендерит полную HTML-страницу (хорошо для SEO и TTI).
  2. Браузер устанавливает WebSocket-соединение через phx-socket.
  3. При событии (клик, ввод, таймер) LiveView обновляет состояние на сервере и отправляет только изменившиеся части HTML как diff.
  4. JS-хук на клиенте применяет diff к DOM — пользователь видит мгновенное обновление.
defmodule MyAppWeb.CounterLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, count: 0)}
  end

  def handle_event("increment", _params, socket) do
    {:noreply, update(socket, :count, &(&1 + 1))}
  end

  def render(assigns) do
    ~H"""
    <div>
      <p>Count: {@count}</p>
      <button phx-click="increment">+1</button>
    </div>
    """
  end
end

Подключение к роутеру

scope "/", MyAppWeb do
  pipe_through :browser

  live "/counter", CounterLive
  live "/users", UserLive.Index
  live "/users/:id", UserLive.Show
end

Что LiveView умеет из коробки

  • Живая валидация форм через phx-change без перезагрузки страницы.
  • Загрузка файлов с прогресс-баром.
  • Оптимистичные обновления UI через JS-команды.
  • PubSub-интеграция для real-time обновлений между пользователями.
  • Навигация между LiveView-страницами без полного перезапроса.
  • Streams для эффективного рендеринга больших списков.

Когда LiveView не подходит

  • Оффлайн-функциональность — нужен JS-фреймворк с локальным хранилищем.
  • Высоконагруженные клиентские анимации — лучше CSS или небольшой JS.
  • Мобильные приложения — только для веба.

Подводные камни

  • Каждый LiveView — отдельный процесс в BEAM: 1000 пользователей = 1000 процессов. При неограниченных данных в assigns память растёт.
  • Состояние теряется при перезапуске сервера — используйте mount/3 для восстановления из БД или сессии.
  • Без JavaScript не обойтись для специфических вещей: JS Hooks нужны для интеграции со сторонними библиотеками.
  • Дебаггинг сложнее: события идут через WebSocket, не видны в стандартных HTTP-логах.
  • Форма с phx-change отправляет запрос при каждом нажатии клавиши — нужен debounce через phx-debounce.
  • Временные артефакты на first render: страница рендерится дважды (HTTP + WebSocket reconnect) — это нормально, но может вызвать мигание.
  • Не путайте push_navigate и push_patch: первый монтирует новый LiveView, второй обновляет текущий.

Common mistakes

  • Сводить liveview к названию метода без lifecycle и failure path.
  • Игнорировать модель runtime: Phoenix 1.8 работает поверх Plug, Endpoint, Router, Controllers/LiveViews, PubSub и OTP supervision.
  • Не отделять validation, authorization, transaction boundary и business logic.

What the interviewer is testing

  • Объясняет liveview через конкретную точку lifecycle в Phoenix (Elixir).
  • Приводит корректный минимальный пример без вымышленных методов или callbacks.
  • Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.

Sources

Related topics