爲什麼我不會錯過 React

作者 | Jack Franklin

譯者 | Sambodhi

策劃 | 凌敏

兩年多以前,我離開了倫敦一家初創公司,在那裏,我負責開發基於 React 的大型電子商務前端,加入了谷歌,從事 Chrome DevTools 的工作。我最初的工作重點是引入 Web 組件,這是一個新的測試基本構建塊,用於開發新的 DevTools 特性和用戶界面。由於最近 Recorder 面板和其他面板的發佈,現在,DevTools 中的很大一部分幾乎都是 Web 組件。

我曾經預計,當我離開以 React 爲中心的角色後,會發覺轉型很困難,並會懷念 React 所提供的東西。結果,我發現轉型要比預期容易得多,並且我真的很享受更接近平臺原語的工作,對我所編寫的軟件保持了更多的控制,在本文中,我想分享一下這個原因。

首先,由於互聯網上有些人總是對那些和他們自己不一樣的觀點很憤怒,因此,我必須清楚地闡明本文不是什麼:

本文應該被解讀爲一個人從每天使用 React 到不去觸碰它的思考,以及這樣做的經驗。我之所以寫下這篇博文,是因爲我驚喜地發現,我是如此享受與 Web 平臺更緊密的合作。

雖然我會用 “React” 作爲我的比較,但你可以合理地將其替換爲任何大型現代框架。

使用平臺

近年來,“使用平臺” 已經成爲一個有點被過度使用和濫用的短語,但是它的核心原理卻讓我產生了共鳴:我們能不能利用瀏覽器和 JavaScript 中的 API,在無需第三方依賴項的情況下,爲我們的用戶開發特性?

注意:這裏的答案並不總是 “是”!我還是想把更多的特性添加到瀏覽器中。但是,相對於十年前,這個原生特性的範圍有了很大的拓展。

一個典型的例子就是構建表單:這曾經是一個使用 React 的合理理由,因爲在這裏,瀏覽器只提供了原始的特性。快進幾年後,在最近的一個項目裏,我可以用 100% 的原生特性來構建具有堅實用戶體驗的表單:

這是不是比使用 npm 的一個庫來爲我打包這一切更費事?有可能!但是我可以通過多寫一些代碼來達到相同的效果,而不會因爲額外的依賴項而影響到我的應用。

保持控制

當我剛開始使用 React 時,我最擔心的就是如何適應自定義元素,但是我真的很喜歡用它們工作。

自定義元素可能會讓你更容易寫出更多的代碼,但是,如果你以前用過任何一個流行的組件庫,那麼你就可以創建出一些令人驚訝的、熟悉的東西,但是有一個關鍵的區別:你不會放棄控制。

React 不允許你自行決定如何以及何時將你的組件渲染到頁面上。你使用它的結構來編寫代碼,它決定何時渲染。10 次中有 9 次——甚至 100 次中有 99 次或更多——這完全符合你的預期。但是 Web 平臺並非十全十美,我猜想大多數 React 開發者都會遇到過這樣的情況:你很渴望能夠調整自己的組件的渲染方式。

如何放棄對渲染過程的控制,將會導致混亂,正如 Gary Bernhardt 所發的這條推文一樣:

爲什麼這段代碼:

console.log(mark ${Math.random()})

alert(mark ${Math.random()})

打印一條日誌,但是顯示兩個警報?因爲 React.StrictMode 隱藏了一條日誌來 “幫助” 我爲併發模式做準備。React 很好,但對於 99.9% 的應用來說,併發模式感覺就是個錯誤。

這種行爲現在已經在 React v18 中有所改變了,但是 React 不得不抑制額外的 console.log 調用,這是它渲染我的應用的結果,這一事實讓我感到驚訝;正是這種在我自己的應用中缺乏控制的情況,已經讓我感到非常警惕。

在軟件開發中,這被稱爲控制反轉(Inversion of Control)。當你使用像 React 這樣的框架時,你的代碼將不再直接控制組件(或函數)何時被調用。你的組件並不直接告訴 React 何時重新渲染它們,而是由 React 決定。你的組件已經把控制讓給了 React。

我們的自定義元素解決方案不會有這種控制的倒置;我們通過明確地調用一個函數(在 lit-html 的例子中,它是一個名爲 html 的帶標籤模板源文本)來控制每一次渲染。

沒有使用 React 這種框架的不利之處在於,你必須考慮重新創建那些原本內置的部分,比如,確保我們批量渲染的基本調度器,或者使這些組件更容易測試的測試助手庫。在這種情況下,你必須仔細考慮你的選擇:如果我們避免使用 React,但最終重新實現了它提供的大部分內容,那麼我們使用框架會可能會更好。在我們的案例中,我們依然認爲這樣的決策是合理的,因爲我們不必重新構建一個具有 React 的所有複雜性的調度器:我們可以構建一個小型的、獨立的實現,只實現我們所需要的東西。

在構建了我們的基本調度器之後,我們可以清楚地知道每個組件的渲染原因和時間,並且當我們需要偏離標準路徑時,我們就能夠實現。這種感覺很有價值:我所開發的每個軟件項目中,都有至少一種組件需要做一些不同的事情來處理奇怪的邊緣情況。

選擇可以輕鬆替換的依賴項

自定義元素缺乏的一個領域是某種形式的 HTML 模板解決方案,它提供了高效的 HTML 重渲染。我肯定會建議使用一個庫來解決這個問題,而我們選擇了 lit-html。lit-html 的魅力在於,它只是我們解決方案中的一小部分。我們本可以選擇 Lit,一個基於自定義元素形成的功能更全面的組件庫,但是這樣做,會導致我們增加依賴項,同時也會失去一定的控制(重申我在這篇博文前面提出的觀點:這不是對 Lit 的批評,對很多人來說 Lit 是正確的選擇!)。

Lit-html 可以確保我們的 HTML 被有效地渲染,並且提供了一套很好的指令,讓我們可以輕鬆地完成常見的任務,如有條件地應用類。雖然沒有 JSX 那麼完美,但是也非常的接近。

最重要的是什麼?它是一個非常小的依賴項(3.3kB gzipped),更重要的是,如果我們需要的話,可以很容易地被替換。這聽起來很消極,甚至很悲觀,但當我們採用一個新的依賴項時,我們要問的一個主要問題是:“如果它消失了會怎樣呢”?

假定 React 已經消失(這並不是說我認爲它會消失)。我們處理這個問題的代價是什麼?我們有幾個選擇:

這兩個選項對我都沒有吸引力;維護一個庫意味着我們要麼什麼都不做,要麼錯過改進和 / 或安全修復;而遷移我們所有的組件,那就是一項浩大的工程了。我確信,一旦出現這樣的情況,React 的復刻將會如雨後春筍般湧現出來,但是不管怎麼說,它都需要很多的努力,經過很多的波折,才能使事情變得更健壯。遷移我們所有的組件,花費會非常大,而且對最終用戶來說,也沒有什麼實際的好處,這對於企業和領導層而言是非常困難的。我們還必須學習一種新的框架(即使它與 React 相似),並且在這個框架中增加我們的專業知識。

這與自定義元素和 Lit-html 形成了鮮明對比。我們可以有很好的信心,自定義元素不會突然消失;它被嵌入到瀏覽器中,並且向後兼容是 Web 平臺的一個核心原則。

如果你在想自定義元素 v0 被移除而改用 v1,請記住 v0 是 Chrome 瀏覽器的特定實驗性規範,而 v1 是一個跨平臺的標準化規範。v0 的目的是收集開發者的反饋,以便爲未來的標準化規範提供參考。

要是 lit-html 從互聯網上消失了呢?我們有同樣的兩個選擇:維護一個復刻,或者取代它。維護復刻並不理想,原因與維護 React 復刻不理想一樣,但有一點不同:lit-html 的範圍要小得多,而且一般來說它是一個小得多的庫。這將減少我們的工作量,使我們能夠在需要時進行修復或改進。

替換 lit-html 將是一項工作,但比替換 React 要少得多:它在我們的代碼庫中純粹是用來讓我們的組件(重新)渲染 HTML。替換 lit-html 仍然意味着我們可以保留我們的業務邏輯,最終保持它們爲最終用戶提供的價值。Lit-Html 是我們系統中的一塊小的 “樂高磚”,React(或 Angular,或類似)是整個 “盒子”。

第三方依賴項的成本

第三方依賴,無論大小,都會有一系列的成本,你的用戶和 / 或開發人員將爲此支付。每個人對這一成本是否值得的看法會有所不同,這取決於你的應用程序和技術棧,但當我考慮添加新的依賴項時,會出現以下一組成本:

  1. 包大小:這個依賴對我們必須在瀏覽器中交付和執行的最終 JavaScript 增加多少權重?對於這個依賴項所提供的東西來說,這個包的大小是否合適和值得?

  2. 突破性變化和升級:如果軟件包有一個大的改動,需要工作來升級到最新版本,會發生什麼?我們是繼續使用舊版本(如果它沒有得到更新或安全修復,那就不太理想),還是投入工作來升級?升級的工作是否可以很快得到優先考慮,或者是我們可能永遠無法完成的工作類型?

  3. 未維護的代碼或問題的風險:誰能說第三方的依賴項可能有特定的漏洞或問題而導致問題?(這並不是批評所有那些孜孜不倦地維護開源軟件的人——但這些事情常會發生)。

Jeremy Keith 在他最近關於信任的文章中指出:

你添加到項目中的每一個依賴項都是多一個潛在的單點故障。

你自己的代碼也是如此(把 “依賴項” 換成“文件”),但關鍵是你有完全的控制,你可能更熟悉它的工作原理,因爲它是在內部編寫的,而且你不需要對其他人負責來修復上游的問題。這並不是說你應該在每個項目上都重新創建一個世界;在自己構建和添加依賴項之間總是有一個很好的平衡,而且沒有任何規則可以決定每次的正確結果。

總結

這篇文章並不是說你不應該接觸依賴項。在迴應 Jeremey Keith 關於信任和第三方依賴項的帖子時,Charles Harries 提出,跨瀏覽器兼容性在歷史上是依賴項的驅動力。

瀏覽器兼容性是庫(尤其是 Jeremy 提到的大庫),如 React 和 Bootstrap-- 向開發者作出的基本承諾之一。

我沒有足夠的時間在 caniuse.com 上瀏覽 Array.prototype.includes 或 MutationObserver 的頁面。Lodash 在其主頁的底部就承諾了跨平臺兼容性。

我完全同意 Charles 的觀點,這也是爲一個瀏覽器開發工具的工作具有優勢的一個領域,因爲我們瞭解用戶對瀏覽器的偏好。

我希望,隨着瀏覽器所支持的基線特性集越來越統一,尤其是 IE 瀏覽器的消亡,我們的行業可以隨着時間的推移,在缺省的狀態下,能夠實現瀏覽器的廣泛內置特性,在絕對必要的情況下進行多重填充,並把框架作爲默認的起點。

作者介紹:

Jack Franklin,谷歌工程師,負責構建 Chrome DevTools。

原文鏈接:

https://www.jackfranklin.co.uk/blog/working-with-react-and-the-web-platform/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/b99HNFNT6gpaF_oISonGNg