Rich Harris 是一位知名的網頁開發者,致力於開發 Svelte.js,一個新穎的單頁應用程式(SPA)框架。
在 2021 年 10 月,他在 JamStack 上發表了一場名為 「單頁應用程式是否毀了網路?」的演講。
我們被要求對這場演講發表意見,因此這篇文章是我們的回應。
首先要說的是,這場演講做得非常好:製作精良、內容周到、幽默風趣、對辯論雙方都很公平,而且整體而言非常合理。我們並不贊同 Harris 先生所說的許多觀點,我們將在下面詳細說明,但我們尊重並欣賞他的意見以及他所開發的技術。
演講一開始對單頁應用程式提出了一些合理的批評,特別是著重於 Instagram 的可用性問題,Instagram 是我們 Facebook 朋友們提供的典型 SPA 實作。他非常公平地審視了 SPA 的缺點,包括但不限於以下列表
在考量了 Instagram 的可用性問題後,Harris 先生這樣說
拜託各位。如果世界上最優秀的前端工程師都無法在沒有 5MB 的 JavaScript 的情況下讓文字和圖片正常運作,那麼我們也許應該放棄網頁平台。
在這裡,我們非常同意 Harris 先生的觀點,但我們認為應該將「網頁平台」改為「JavaScript 網頁平台」,因為 Instagram 正是如此。
我們還想進一步澄清,單頁應用程式和框架通常只是忽略了實際的網頁平台,也就是原始的、REST 風格的網頁模型,只是作為一個引導機制。
Harris 先生接著談到多頁應用程式(MPA)的問題,MPA 是我們都熟悉的「傳統」點擊連結載入 HTML 頁面的網頁應用程式,在某種程度上正被 SPA 取代。
下面,我們將探討他概述的各種問題,這些問題對於「標準」MPA 來說都是真實的,我們將示範如何使用以超媒體為導向的技術 htmx 的 MPA 來解決這些問題。
標準 MPA 的一個普遍問題是,它們在每次請求時都會發出完整的頁面重新整理。這表示,當發出請求時,影片或音訊播放器之類的東西會被替換,因此會停止播放。
這個問題可以在 htmx 中透過 hx-preserve
屬性來解決,該屬性會告訴 htmx 在請求之間保留特定的內容。
在存在無限滾動行為(大概是透過某種 JavaScript 實作)的情況下,返回按鈕在 MPA 中將無法正常運作。我想指出的是,無限滾動的存在讓人對 MPA 這個詞產生質疑,因為 MPA 傳統上會使用分頁而不是無限滾動。
也就是說,使用 htmx 可以非常輕鬆地實現 無限滾動,其方式是以超媒體為導向且顯而易見。結合 hx-push-url
屬性,歷史記錄和返回按鈕可以正常運作,開發人員只需付出很少的努力,而且所有內容都有漂亮的複製貼上網址,SPA 社群中的人們有時稱之為「深層連結」。
漂亮的轉場確實很好看。不過,我們認為設計師往往高估了它們對應用程式可用性的貢獻。沒錯,示範影片很精彩,但在第 20 次點擊時,使用者通常只希望 UI 快點完成。
話雖如此,htmx 支援使用 標準 CSS 轉場來實現動畫效果。顯然,使用這些純 CSS 技術可以實現的功能是有限的,但我們相信這可以讓您在 80/20 的情況下實現 80。 (或者,也許是 95/5 情況下的 95。)
Harris 先生主要關注「糟糕的廣告技術」是造成網頁可用性問題的罪魁禍首,誰能為當今大多數網站向使用者提供的 2.5MB 的追蹤、間諜軟體和廣告軟體的有效負載辯護呢?Harris 先生指出,SPA 可以透過一次載入這堆垃圾來緩解這個問題,而不是像 MPA 那樣在每次請求時重複載入。
現在,一個普通的 MPA 通常會在第一次請求後快取這些垃圾,因此至少下載成本與 SPA 大致相同。但 MPA 必須在每個頁面上再次執行這堆垃圾,這會消耗 CPU 並可能導致不良的使用者體驗。
但是,我們注意到,由 htmx 驅動的 MPA 與 SPA 具有完全相同的特性:廣告垃圾會在第一次請求時下載並執行一次,之後,所有請求都會相對輕量地替換 DOM 元素。
這是一個有效的觀點:使用 MPA 風格的應用程式,您的 UI 互動會受到伺服器回應請求的速度(即延遲)的限制。部分延遲是網路延遲,如果不放棄傳統網頁應用程式的巨大簡化方面:集中式資料儲存,就很難克服。但是,網路速度很快並且正在變得更快,並且有眾所周知的技術可以最佳化伺服器延遲(即伺服器傳回回應的速度),這些技術經過數十年開發,用於監控和最佳化此回應時間。SQL 調校、Redis 快取等,所有這些都已經建立,並且使 100 毫秒以下的回應成為合理目標。許多 htmx 使用者都表示基於 htmx 的應用程式感覺非常快,但我們不會假裝延遲不是一個需要考慮的問題。
當然,延遲問題的問題在於它們會使應用程式感覺遲緩。但是,和您一樣,我們也使用過許多遲緩的 SPA,因此我們必須說,僅僅採用 SPA 框架並不能很好地解決這個問題。最重要的是,與伺服器樂觀地同步資料可能會導致極難理解的資料一致性問題,以及整體應用程式複雜性的顯著增加,我們稍後將回到這個主題。
GitHub 的確有 UI 錯誤。但是,它們都不難解決。
htmx 提供了多種方式來更新目標元素以外的內容,所有這些都非常簡單,並且其中任何一種都可以解決 Harris 先生指出的 UI 一致性問題。
將 GitHub UI 問題與 Harris 先生先前指出的 Instagram UI 問題進行比較:解決 Instagram 問題將需要更複雜的工程工作。
Harris 先生接著討論了「過渡應用程式」的概念,它混合了 SPA 和 MPA 技術。這個術語是合理的,我們將看看這個術語是否會在業界流行起來。
我們經常建議將 htmx 用於應用程式中適合保持簡單的部分,然後在需要時使用其他技術:alpine.js、hyperscript、一個小型的反應式框架等。
因此,我們可以在某種程度上同意 Harris 先生的觀點,並建議採用「過渡」方法來進行網頁開發,儘管我們建議盡可能傾向於 MPA/超媒體,而 Harris 先生似乎相當肯定會傾向於 SPA/JavaScript。
不幸的是,Harris 先生沒有討論一個主題,我們認為這可能是因為他沒有看到它。他是一位熱衷於該語言的 JavaScript 開發人員,並且沉浸在前端框架的工程文化中,因此當前 JavaScript 前端開發的複雜性對他來說似乎很自然。然而,對於我們許多人來說,JavaScript 生態系統簡直是過度複雜。事實上,鑑於大多數網頁應用程式的需求,這實在是太可笑了。
Harris 先生接著提到許多「過渡」技術:React 伺服器元件(他稱之為「像網路上的 HTML,但要複雜得多」)、Marko(正在進行「部分水合」)、Quik(顯然會積極延遲載入),它們都是卓越的工程成就,但我們也必須說,它們都非常複雜。
不幸的是,這是目前前端開發文化的一部分:在應用程式框架、建置工具鏈、部署模型等方面容忍極高的複雜性,並且當所有這些複雜性導致問題時,通常會提供更多的複雜性作為答案。
「簡單」是不屑一顧的,「複雜」是高度讚揚。
這種複雜性讓當今許多開發人員和開發團隊感到不知所措。正如 Harris 先生在討論 Instagram 時指出的那樣,即使是世界上一些最優秀的前端工程師似乎也無法控制這一切。
因此,這裡存在一個文化問題。
還有一個技術問題。
這個技術問題可以總結為「超媒體方法」與「遠端程序呼叫(RPC)方法」之間的對立。
當網路應用程式從多頁應用程式(MPA)轉向單頁應用程式(SPA)時,它們在不知不覺中採用了RPC方法進行應用程式開發:AJAX轉向JSON作為資料序列化格式,並在很大程度上(而且是正確地)放棄了超媒體的概念。這種對超媒體方法的放棄,是由於傳統MPA在可用性方面存在公認的問題所驅動的。
然而,事實證明,這些可用性問題通常可以通過使用超媒體方法來解決:我們需要的不是為了RPC而放棄超媒體,而是當時和現在都需要更強大的超媒體。
這正是htmx所提供的。
透過回歸超媒體方法,您可以建構相當複雜的網路應用程式,以解決哈里斯先生關於MPA的許多疑慮,而且複雜程度遠低於大多數流行的SPA框架。此外,在不經過太多思考的情況下,您將獲得Roy Fielding概述的關於真正RESTful架構的所有優勢。
超媒體架構是否適用於所有網路應用程式?顯然不是。
它是否適用於許多,甚至可能大多數的網路應用程式?我們當然認為如此,至少在某種程度上是這樣。
現在我們來談談這次演講中最具情感色彩的主張:「JavaScript的船已開出」,我們應該接受它將成為未來網路開發中的主導程式語言。
哈里斯先生認為,邊緣運算將成為最終消除對JavaScript的剩餘零星反對力量的驅動力。
我們對此不太確定。
相反地,我們不認為邊緣運算會在可預見的未來,甚至永遠,在大多數網路應用程式中佔有一席之地。CPU很便宜,網路速度很快而且不斷提高,而微服務則是一團糟。
而且,與哈里斯先生所說的相反,今天的趨勢並不明顯有利於JavaScript。五年前,我們作為JavaScript反抗運動的創始成員,曾對阻止JavaScript巨頭的任何希望感到絕望。但是,隨後發生了一些意想不到的事情:Python崛起,同時JavaScript卻停滯不前。
這種JavaScript在2010年代中期達到頂峰的趨勢,也可以在GitHub上觀察到。
現在,這是否意味著JavaScript最終會「輸給」Python並消失?
當然不是。JavaScript是網路的核心技術,將永遠與我們同在。沒有它,我們就無法建構htmx(或hyperscript),因此我們非常感謝JavaScript。
但這確實意味著,網路的未來不一定完全屬於JavaScript,就像五年前的情況一樣。
我們喜歡談論HOWL堆疊:您想要的任何後端語言上的超媒體(Hypermedia On Whatever you’d Like)。這個想法是,透過回歸(更強大的)超媒體架構,您可以使用任何您喜歡的後端語言:Python、Lisp、Haskell、Go、Java、C#,任何語言都可以。如果您喜歡,甚至可以使用JavaScript。
由於您使用超媒體和HTML進行伺服器互動,因此您不會感受到巨大的JavaScript前端帶來的在後端採用JavaScript的壓力。您當然仍然可以使用JavaScript(也許以alpine.js的形式),但您可以使用它原本的用途:作為一個輕量級的前端腳本語言來增強您的應用程式。或者,如果您夠勇敢,也許可以嘗試使用hyperscript來滿足這些需求。
這是一個我們更希望生活在其中的世界:多種程式語言選擇,每種語言都有自己的優勢、技術文化和蓬勃發展的社群,所有這些都能透過更強大的超媒體的魔力,而不是SPA與Node以JSON對話的巨石,參與網路開發世界。畢竟,多樣性是我們的力量。
總之,