Gumroad 為何沒有選擇 htmx

Sahil Lavingia

在 Gumroad,我們最近著手進行一個名為 Helper 的新專案。身為 CEO,我最初對在這個專案中使用 htmx 相當樂觀,即使有些團隊成員沒那麼熱衷。

我的樂觀來自於先前使用 React 的經驗,React 對我們的需求來說常常感覺過於複雜。我認為 htmx 可以是一個讓前端保持超級輕巧的好方法。

Gumroad Red
使用 htmx 的原始碼 - 點擊圖片以檢視

事實上,我曾在 Slack 上和我們的團隊分享過這種想法

「https://htmx.dev.org.tw/ 或許是一種開始加入簡單互動的方式」

一開始,這看起來很有希望!正如我們 Gumroad 的一位工程師所精闢地說

「HTMX(官方地說)是一個梗,用來嘲諷 JS 的領域變得過於複雜 - 就像 tailwind 只是 inline CSS 的另一種語法,HTMX 是 inline JS 的另一種語法。」

然而,與在我們的工具組中找到自己定位的 Tailwind 不同,htmx 對於我們的目標來說無法擴展,而且至少在我們的用例中,並沒有為我們的客戶帶來最佳的使用者體驗。

原因如下

  1. 直覺與開發者體驗:雖然使用 htmx 也可以做到正確的事,但我們發現使用 Next.js 讓所有事情運作起來更加直覺和有趣。使用 Next.js 的開發流程感覺很自然,而使用 htmx 時,它常常感覺不自然且勉強。例如,在建構具有動態驗證和條件式欄位的複雜表單時,我們發現自己撰寫了複雜的伺服器端邏輯來處理在 React 中會很簡單的客戶端操作。

  2. UX 限制:htmx 最後將我們的應用程式推向 Rails/CRUD 的方法,這預設導致了非常差(或至少是乏味且通用)的使用者體驗。我們發現自己不斷地與這種傾向作鬥爭,這適得其反。例如,為我們的流程建構器實作拖放介面時,使用 htmx 被證明是一個重大的挑戰,需要使用與我們可以使用 React 函式庫實現的流暢體驗相比之下顯得笨拙的解決方案。

  3. AI 和工具支援:值得注意的是,由於缺乏開源的訓練資料,AI 工具非常熟悉 Next.js,但不太熟悉 htmx。這與 Rails 面臨的問題類似。雖然這不是一個決定性的因素,但它確實影響了我們的開發速度以及尋找問題解決方案的難易程度。當我們遇到問題時,React/Next.js 可用的豐富資源使故障排除速度快得多。

  4. 可擴展性問題:隨著專案複雜性的增加,我們發現 htmx 很難滿足我們的需求。最初吸引我們的簡單性,當我們嘗試實作更複雜的互動和狀態管理時,開始感到侷限。例如,當我們加入像是即時協作和複雜的資料視覺化等功能時,使用 htmx 的以伺服器為中心的方法,管理多個元件的狀態變得越來越困難。

  5. 社群與生態系統:React/Next.js 生態系統龐大且成熟,為我們遇到的幾乎所有問題提供了解決方案。使用 htmx,我們常常發現自己在重新發明輪子,或是犧牲功能。當我們需要整合第三方服務和函式庫時,情況變得特別明顯,這些服務和函式庫通常具有 React 綁定,但沒有 htmx 的對應版本。

Gumroad Green
使用 NextJS 的原始碼 - 點擊圖片以檢視

最終,我們改用 React/Next.js,這對於建構我們一直以來追求的複雜 UX 來說非常適合。我們對這個決定感到滿意 - 目前是這樣。它使我們能夠更快地行動、創造更吸引人的使用者體驗,並利用豐富的現有工具和函式庫。

Gumroad Helper Before After
Gumroad Helper 前後比較 - 點擊圖片以檢視

這次的經驗強化了一個寶貴的教訓:雖然考慮輕量級的替代方案很重要,但選擇能夠隨著專案成長並支援長期願景的技術同樣至關重要。對於 Helper 來說,React 和 Next.js 已被證明是這樣的選擇。

自從我們改用 React/Next.js 後,我們已經能夠大幅提升核心客戶的應用程式使用者體驗。

  1. 拖放功能:我們流程建構器的主要功能之一是能夠透過拖放重新排序步驟。雖然可以使用 htmx 實作拖放,但我們發現可用的解決方案感覺笨拙,並且需要大量的自訂 JavaScript。相比之下,React 生態系統提供了像 react-beautiful-dnd 這樣的函式庫,只需最少的設定即可提供流暢、可存取的拖放功能。

  2. 複雜的狀態管理:每個流程步驟都有自己的一組配置和條件邏輯。當使用者編輯這些配置時,我們需要即時更新 UI 以反映變更及其對其他步驟的影響。使用 htmx,這將需要大量的伺服器往返或複雜的客戶端狀態管理,這與 htmx 以伺服器為中心的理念背道而馳。React 的狀態管理解決方案(例如 useState 或更進階的選項,如 Redux)使這變得更加簡單。

  3. 動態表單生成:每個步驟類型的配置都不同,並且可以根據使用者輸入而變更。使用 React 的元件模型,產生這些動態表單並處理它們的狀態更加直覺。使用 htmx,我們發現自己撰寫了更複雜的伺服器端邏輯來產生和驗證這些表單。

  4. 即時協作:雖然此螢幕截圖中看不到,但我們實作了允許多個使用者同時編輯流程的功能。使用 WebSockets 和 React 實作此功能相對簡單,而使用 htmx,則需要更複雜的伺服器端邏輯和自訂 JavaScript 來處理即時更新。

  5. 效能最佳化:隨著流程變得更大更複雜,我們需要對渲染最佳化進行細粒度的控制。React 的虛擬 DOM 和像 useMemo 和 useCallback 這樣的 Hooks 使我們能夠以 htmx 無法輕易獲得或直覺的方式最佳化效能。

值得注意的是,雖然使用 htmx 並非無法克服這些挑戰,但我們發現解決這些問題通常會讓我們偏離 htmx 的優勢,轉向在以 JavaScript 為主的環境中感覺更自然的解決方案。這個意識是我們決定改用 React 和 Next.js 的一個關鍵因素。

我們承認 htmx 可能非常適合許多專案,特別是那些具有較簡單的互動模型或建立在現有伺服器渲染應用程式之上的專案。我們的經驗並不能否定其他人在 htmx 中發現的好處。關鍵是了解專案的特定需求,並選擇最符合這些要求的工具。

在我們的情況下,Helper 介面的複雜、有狀態的性質使 React 和 Next.js 更適合。然而,我們仍然感謝 htmx 的方法,並且可能會考慮將其用於未來其優勢更符合我們需求的專案。

也就是說,隨著我們需求的發展和新技術的出現,我們隨時準備重新評估我們的技術堆疊。誰知道未來會發生什麼?

</>