Phoenix LiveView:讓你的網頁像聊天室一樣即時
如果你用過現代網站,可能會注意到有些網站「感覺很快」—按個讚立刻顯示、留言即時出現、購物車數量瞬間更新,完全不用等頁面重新整理。也許是 Facebook 的動態牆、也許是線上協作工具、也許是即時聊天室。
但你知道嗎?這些「即時更新」的背後,傳統上需要前端工程師和後端工程師寫兩套程式碼,用不同語言,還要小心翼翼地讓它們溝通。
如果我告訴你,有個框架讓你只用一種語言就能做到這些,而且不用寫複雜的 JavaScript,你相信嗎?
這就是 Phoenix LiveView 的魔法。
傳統方式 vs LiveView:郵件 vs 電話
想像你要跟朋友討論晚餐吃什麼。
傳統方式(像寄信)
你傳訊息:「要吃什麼?」 等手機重新整理… 朋友回覆:「義大利麵?」 你又傳:「好啊,幾點?」 等手機重新整理… 朋友回覆:「7點」
這就是傳統的前後端分離架構:
- 前端用 React/Vue 寫 JavaScript
- 後端用 Rails/Django/Node.js 寫 API
- 每次互動都要「寄信」(HTTP 請求)然後等回覆
- 兩邊要維護兩套程式碼,還要確保格式對得上
LiveView 方式(像打電話)
你打電話給朋友,即時討論: 「要吃什麼?」「義大利麵」「好,幾點?」「7點」 搞定!
這就是 Phoenix LiveView 的運作方式:
- 只用 Elixir 一種語言寫後端邏輯
- 透過 WebSocket 保持連線
- 畫面變化自動推送到瀏覽器
- 不用寫 API、不用寫一堆 JavaScript
LiveView 的超能力:用一種語言統治全部
超能力 1:真正的即時互動
LiveView 透過 WebSocket 技術,讓伺服器和瀏覽器保持持續連線。這意味著:
- 按讚立刻更新:不用重新整理頁面
- 多人同時編輯:就像 Google Docs 那樣
- 即時聊天:訊息秒傳
傳統方式要用 JavaScript 輪詢(polling)或手動建立 WebSocket 連線,LiveView 自動幫你處理好。
超能力 2:只用一種語言(Elixir)
看看傳統方式要寫多少東西:
// 前端(React)- JavaScript
const [count, setCount] = useState(0);
const increment = async () => {
const response = await fetch('/api/increment', { method: 'POST' });
const data = await response.json();
setCount(data.count);
};
# 後端(Rails)- Ruby
class CountersController < ApplicationController
def increment
@counter = Counter.find(params[:id])
@counter.increment!
render json: { count: @counter.value }
end
end
兩種語言、兩個檔案、還要確保格式一致。
現在看看 LiveView 的做法:
# 只要一個檔案(Elixir)
defmodule MyAppWeb.CounterLive do
use Phoenix.LiveView
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 %></p>
<button phx-click="increment">+1</button>
</div>
"""
end
end
一種語言、一個檔案、自動即時更新。點擊按鈕時,LiveView 自動:
- 觸發
increment
事件 - 更新
count
狀態 - 只更新變化的部分推送到瀏覽器
不用寫 API、不用處理 JSON、不用管狀態同步。
超能力 3:聰明的部分更新
LiveView 不會像傳統方式那樣每次都重新整理整個頁面。它只傳送變化的部分。
假設你有個待辦清單,新增一個項目:
- 傳統方式:重新下載整個 HTML(200KB)
- LiveView:只傳送新的那一行(2KB)
這就是為什麼 LiveView 即使透過伺服器運作,速度還是超快。
超能力 4:高並發能力(感謝 Elixir)
LiveView 建構在 Elixir 語言之上,而 Elixir 運行在 Erlang 虛擬機(BEAM)上。BEAM 的特色是:
- 輕量級進程:每個 LiveView 連線只用幾 KB 記憶體
- 超強並發:單台伺服器可以處理數百萬個連線
- 容錯設計:一個連線掛掉不會影響其他人
這就是為什麼 Discord、WhatsApp 這些需要處理大量即時連線的服務都用 Erlang/Elixir。
LiveView 適合做什麼?
絕配場景
- 即時聊天室:訊息即時送達,不用輪詢
- 協作工具:多人同時編輯,像 Google Docs
- 即時儀表板:股價、監控數據即時更新
- 互動表單:輸入時立刻驗證,不用等提交
- 遊戲:簡單的多人線上遊戲
不適合的場景
- 極度複雜的 UI 動畫:這種還是 React/Vue 比較適合
- 完全離線的應用:LiveView 需要網路連線
- 純靜態內容網站:如果網站內容完全不需要互動,靜態生成(如 Jekyll、Hugo)更適合
和其他框架比起來如何?
特性 | LiveView | React/Vue | 傳統 MVC |
---|---|---|---|
語言數量 | 1 種(Elixir) | 2 種(JS + 後端) | 1 種(但不即時) |
即時更新 | 內建 | 需要額外設定 | 需要輪詢或手動 WebSocket |
學習曲線 | 中等(要學 Elixir) | 陡峭(前後端都要會) | 平緩 |
並發能力 | 極強 | 看後端 | 看後端 |
適合場景 | 即時互動應用 | 複雜 UI | 傳統網站 |
實戰案例:按讚功能
假設你要做個「按讚」功能,點擊後立刻更新數字。
傳統方式需要:
- 前端點擊事件處理(JavaScript)
- 發送 API 請求(Fetch/Axios)
- 後端接收請求更新資料庫
- 回傳 JSON
- 前端更新畫面
LiveView 只需要:
defmodule MyAppWeb.PostLive do
use Phoenix.LiveView
def handle_event("like", _params, socket) do
# 更新資料庫
post = Posts.add_like(socket.assigns.post)
# 畫面自動更新
{:noreply, assign(socket, post: post)}
end
def render(assigns) do
~H"""
<button phx-click="like">
❤️ <%= @post.likes %> 人按讚
</button>
"""
end
end
點擊按鈕 → LiveView 自動呼叫 like
事件 → 更新資料 → 畫面即時更新。
沒有 API、沒有 JSON、沒有狀態管理地獄。
結語
下次當你需要做即時互動功能時,想想看:
- 你真的需要前後端分離嗎?
- 你真的想維護兩套程式碼嗎?
- 你真的想花時間對 API 格式嗎?
如果答案是「不想」,那 Phoenix LiveView 可能就是你要的解答。
LiveView 從 2019 年發布以來,已經被用在無數生產環境中,證明了「不一定要前後端分離才能做出好的即時應用」。
記住:好的工具不是讓你寫更多程式碼,而是讓你用更少的程式碼做更多的事。