重點摘要: 如果您將 API 分割為資料 API 和應用程式 API,如這裡所提倡的,您應該考慮將您的應用程式 API 從 JSON 改為超媒體 (HTML),並使用像 htmx 這樣的以超媒體為導向的函式庫,以獲得超媒體模型的優勢(簡單性、可靠性、彈性等)。
最近,Max Chernyak 寫了一篇名為 不要建立通用 API 來驅動您自己的前端 的文章。他的重點摘要是這樣:
除非您在擁有聯合前端或 GraphQL 的大型公司工作,否則 YAGNI (You Aren't Gonna Need It, 你不會需要它)。
然後他討論了通用 API 和您的應用程式 API 的一些不同需求。他列出了以下通用 API 的需求:
以及這些應用程式 API 的需求:
我將這種需求不一致的問題稱為資料/應用程式 API 阻抗不匹配問題。
Max 的建議是將 API 分割成兩個「一半」:一個通用 API 和一個應用程式 API
我建議您停止將您的前端視為某種通用 API 用戶端,並開始將其視為您的應用程式的一半。
想像一下,如果您可以只發送整個「頁面」的 JSON。為
/page/a
建立一個端點,並在那裡呈現/page/a
的整個 JSON。對每個頁面都這樣做。不要強迫您的前端開發人員發送一堆單獨的請求來呈現複雜的頁面。停止用人為的限制來煩擾他們。讓你們自己一致。
我完全同意 Max 關於這裡的問題。
我特別要強調的是,通用 API 需要保持穩定,而應用程式 API 必須快速變更以滿足應用程式的需求。
Jean-Jacques Dubray 在這篇文章中敘述了 API 設計師的以下悲慘情況:
我最近工作中最糟糕的部分是為前端開發人員設計 API。對話不可避免地會變成:
開發人員 – 所以,這個螢幕有資料元素 x、y、z… 你可以建立一個回應格式為 {x: , y:, z: } 的 API 嗎?
我 – 好
這完美地概括了 Max 所注意到的緊張關係,其中 API 工程師希望設計通用、穩定的 API,但卻受到快速變化的 UI 和複雜的資料需求的擺佈,這些需求通常最好在伺服器端解決。
正如 Max 指出的那樣:
您可以保持「頁面 a」的單純,只做它需要做的事情。您可以對「頁面 a」進行徹底的錯誤、安全性、效能測試。您甚至可以在一個大型 SQL 查詢中獲取「頁面 a」的所有內容。
所以,再次強調,我完全同意 Max 的觀點,即存在資料/應用程式 API 阻抗不匹配的問題,並且我讚賞他建議將 API 分割成兩個,而不是像 GraphQL 那樣轉向解決方案。
但是,還有下一步要採取
一旦您將應用程式 API 從通用資料 API 分割開來,您就不再受限於公開資料 API 的約束,並且可以自由地重新考慮該應用程式 API 的整個形式。我們可以對它做任何我們想做的事,所以讓我們在思考上更加廣闊。
請注意,應用程式 API 的核心問題是快速變更和頁面(或資源)特定的調整。事實證明,我們有一種非常好的技術來處理確切的這個問題:超媒體!
透過 HATEOAS,超媒體使 API 變動不再那麼成問題。當您更改超媒體 API 的形狀時,這沒關係:新的 API 只會反映在伺服器返回的新的 HTML 中。您可以新增和修改端點,並且(在第一近似值中)您的用戶端(也就是瀏覽器)不需要更新。
瀏覽器只會看到新的 HTML,並且驅動它們的人類會對新的功能做出適當的反應。
因此,雖然我覺得 Max 的方向是正確的,但我也認為他走得不夠遠:一旦您在心理上跳躍,透過將兩者分割為不同的關注點來解決資料/應用程式 API 阻抗不匹配的問題,那麼只需再往前走一步,就可以重新發現超媒體的優勢。
您可能會反對說:「哦,但是超媒體應用程式不是很好用,我們不想回到 Web 1.0。」
這是一個完全合理的反對意見,但是人們一直在研究這個問題,現在有許多函式庫可用,可以解決 HTML 在超媒體模型中的可用性問題。
我最喜歡的兩個是 unpoly,當然還有我自己的 htmx。
如果您切換到超媒體應用程式 API(這實際上只是意味著「像以前一樣使用 HTML」),那麼您將獲得 REST-ful Web 模型的所有優勢(簡單性、可靠性等),以及成熟 Web 框架中伺服器端呈現的優勢(快取、SQL 調整等)。
而且,透過選擇像 htmx 這樣的以超媒體為導向的前端技術,您可以在該模型中建立卓越的使用者體驗。
一切舊事物都再次成為新事物,但這一次,它會更好一點。