反應(yīng)式JavaScript:前端架構(gòu)的演變
譯文?譯者 | 李睿
審校 | 孫淑娟
當(dāng)今軟件開發(fā)中最具活力的領(lǐng)域之一是前端架構(gòu)。而一些創(chuàng)新者正在推動(dòng)最新技術(shù)的發(fā)展,以設(shè)計(jì)出更強(qiáng)大的方法來構(gòu)建動(dòng)態(tài)用戶界面。這項(xiàng)工作大部分都在以驚人的速度進(jìn)行,而且是公開的。
多虧有許多開源JavaScript項(xiàng)目,例如SvelteKit、Solid、React、Qwik和Astro,使企業(yè)在網(wǎng)絡(luò)未來的發(fā)展中處于領(lǐng)先地位。以下是理解操作的指南。
什么是水合?
改善現(xiàn)代前端架構(gòu)的大部分活動(dòng)都集中在水合(hydration)上。為了理解水合作用是什么,以及為什么它是現(xiàn)代前端架構(gòu)的核心,人們需要了解一些概念。為了實(shí)現(xiàn)反應(yīng)性的奇跡,每個(gè)框架都必須處理下圖所示的三個(gè)方面。
圖中的基本信息是框架負(fù)責(zé)構(gòu)建視圖、保持狀態(tài)并管理它們之間的交互(如果熟悉MVC模式,就會(huì)得到呼應(yīng))。
一旦這三個(gè)部分就位,就可以開始了。用戶可以看到頁面并與之交互。
而默認(rèn)的方法是簡(jiǎn)單地獲取客戶端所需的一切——框架、響應(yīng)式代碼和狀態(tài),并將其發(fā)送過來。然后,客戶端(瀏覽器)執(zhí)行顯示框架(也就是繪制UI)、解釋JavaScript和綁定狀態(tài)的工作。
這種方法具有簡(jiǎn)單性的好處,對(duì)于工作中的代碼和試圖理解它的人員來說都是如此。它也有一個(gè)很大的缺點(diǎn):最初的頁面渲染必須等待所有內(nèi)容,并且用戶必須忍受所有的網(wǎng)絡(luò)和瀏覽器波動(dòng)。這里要小心,否則頁面將重新排列到最終布局中,但頁面并不好看。
這激發(fā)了開發(fā)人員嘗試首先在服務(wù)器上渲染初始頁面(服務(wù)器端渲染,SSR)并將其發(fā)送過來。然后,在發(fā)送和引導(dǎo)其余代碼和狀態(tài)的同時(shí),用戶可以查看合適的頁面。這是一個(gè)很好的簡(jiǎn)化,但這是基本的想法。
獲得基本布局所需的時(shí)間稱為首次內(nèi)容繪制(FCP)。頁面需要達(dá)到的下一個(gè)里程碑是通過交互時(shí)間(TTI)來衡量的,這意味著用戶能夠?qū)嶋H使用頁面的時(shí)間。
獲取初始頁面并使其具有交互性的過程——即水合作用。
服務(wù)器端渲染的限制
其底線是服務(wù)器端渲染(SSR)傾向于改善首次內(nèi)容繪制(FCP)但惡化交互時(shí)間(TTI)。因此,其目標(biāo)是在兩者之間取得平衡,同時(shí)最大化這兩者,同時(shí)希望保持愉快的開發(fā)人員體驗(yàn)(DX)。
在這一努力中,已經(jīng)提出、采用、放棄、修改和結(jié)合了多種方法來改善水合作用。一旦了解實(shí)現(xiàn)細(xì)節(jié),就會(huì)驚訝于它變得多么復(fù)雜。首次內(nèi)容繪制(FCP)和惡化交互時(shí)間(TTI) 如何均衡?這聽起來很容易,但事實(shí)并非如此。
造成這種復(fù)雜性的一個(gè)原因是,正處于對(duì)所有權(quán)衡進(jìn)行排序的中間。這是一個(gè)正在展開的場(chǎng)景。但是,一旦明確前進(jìn)的方向,應(yīng)該期望出現(xiàn)的客戶端架構(gòu)會(huì)產(chǎn)生兩個(gè)結(jié)果:首先,它應(yīng)該創(chuàng)建感覺“下一代”的網(wǎng)絡(luò)應(yīng)用程序,就像當(dāng)今精心構(gòu)建的應(yīng)用程序提供比幾年前更好的體驗(yàn)一樣。
其次,也許更重要的是,改進(jìn)的客戶端架構(gòu)應(yīng)該會(huì)產(chǎn)生深遠(yuǎn)的影響,而不僅僅是更好的性能。通過深入研究和解決復(fù)雜性,前端工程師將為系統(tǒng)和思維找到更好的模型。更好的架構(gòu)實(shí)際上代表了更強(qiáng)大的啟發(fā)方法。這會(huì)帶來通常無法預(yù)測(cè)的后續(xù)效益。
人們可以通過反應(yīng)性本身看到這一點(diǎn)。反應(yīng)性突然出現(xiàn),是因?yàn)樗峁┝艘环N將狀態(tài)綁定從開發(fā)人員的大腦轉(zhuǎn)移到框架的方法。但好處并不止于此。架構(gòu)不僅變得更簡(jiǎn)單,而且更加一致。這使性能和功能得到全面提升。
由于現(xiàn)代JavaScript框架同時(shí)包含服務(wù)器和客戶端,因此這些開發(fā)的結(jié)果可能會(huì)對(duì)一般的應(yīng)用程序架構(gòu)產(chǎn)生廣泛的影響。
改善水合作用的方法
改善水合狀況的基本訣竅是更細(xì)致地看待事物。通過將視圖、交互性和狀態(tài)分解為更小的部分,可以逐步加載和激活它們,并針對(duì)FCP和TTI進(jìn)行優(yōu)化。以下是一些方法的介紹。
完全避免JavaScript
最佳實(shí)踐中采用的一種方法是,為那些根本不需要JavaScript的頁面分析站點(diǎn)。這與多頁應(yīng)用程序(MPA)的新概念有關(guān)。它是單頁應(yīng)用程序(SPA)和逐頁導(dǎo)航(默認(rèn)Web行為)之間的中間地帶。這里的想法是找到可以立即作為HTML 和資產(chǎn)發(fā)布的應(yīng)用程序部分,從而獲得盡可能最佳的搜索引擎優(yōu)化(SEO)和加載時(shí)間。
例如,在SvelteKit中可以看到無JS方法。當(dāng)然,這對(duì)于那些需要反應(yīng)式交互的頁面沒有任何作用??蚣苋匀槐仨氃诔洚?dāng)單頁應(yīng)用程序(SPA)的頁面上解決水合作用。
孤島架構(gòu)
Astro倡導(dǎo)孤島架構(gòu)的理念。其目的是確定頁面的哪些部分是靜態(tài)的,哪些部分需要反應(yīng)性。有了這些知識(shí),可以通過忽略永遠(yuǎn)不會(huì)更改的框架內(nèi)容來微調(diào)頁面的加載,然后僅根據(jù)需要加載其他架構(gòu)。
了解這個(gè)想法很有用,需要注意它的目標(biāo)是改進(jìn)單頁應(yīng)用程序(SPA)。也就是說,識(shí)別的所有靜態(tài)內(nèi)容都可以放在那里,在不影響性能的情況下完成工作。所有客戶端狀態(tài)和導(dǎo)航都將得到維護(hù)。
從好的方面來說,這種方法允許延遲加載每個(gè)孤島,直到發(fā)生一些需要它的事情(例如,單擊鼠標(biāo)滾動(dòng)到視圖中)。從不好的方面來說,在實(shí)踐中,它通常會(huì)導(dǎo)致負(fù)載發(fā)生在特別不合時(shí)宜的時(shí)刻(就像用戶正在做某事一樣)。
延遲加載的邊界
JavaScript庫(kù)React的Suspense組件等功能提供了一種方法,可以將基本的水合模型保持在適當(dāng)?shù)奈恢?,但將其沿邊界分解,然后延遲加載。這樣做的好處是可以保留大部分熟悉的過程,但缺點(diǎn)是需要開發(fā)人員進(jìn)行大量思考和調(diào)整才能獲得良好的結(jié)果。
此外,延遲加載只能提供這么多幫助,因?yàn)榭蚣艿拇蟛糠謨?nèi)容仍然需要預(yù)先交付。
可恢復(fù)性
可恢復(fù)性是Qwik框架引入的一個(gè)想法。Qwik深入研究了應(yīng)用程序的元素,并在它們之間創(chuàng)建了惰性邊界(在某種程度上,可以將其視為一種非常復(fù)雜的延遲加載邊界形式)??苫謴?fù)性意味著客戶端可以從服務(wù)器停止的地方恢復(fù),并以細(xì)粒度的方式保持同步。
服務(wù)器組件
React正在推出服務(wù)器組件的想法和稱為流的相關(guān)性能改進(jìn)。以下是對(duì)服務(wù)器組件如何工作的描述。本質(zhì)上,服務(wù)器組件允許用戶識(shí)別應(yīng)用程序的哪些部分可以完全在服務(wù)器上運(yùn)行,從而避免任何客戶端的渲染損失。
流媒體
流媒體是另一種與Suspense相關(guān)的不斷發(fā)展的React技術(shù)。這里的想法是允許在服務(wù)器上準(zhǔn)備好所有必需的數(shù)據(jù)之前,將HTML等框架內(nèi)容發(fā)送到客戶端。然后,可以在組件交互發(fā)生時(shí)應(yīng)用這種方法。
部分水合或漸進(jìn)水合
這些條款讓事情變得有點(diǎn)混亂。Astro將其孤島架構(gòu)描述為部分水合作用。簡(jiǎn)而言之,一次只有頁面的某些元素被水合。這有時(shí)也稱為漸進(jìn)式水合作用。這兩個(gè)術(shù)語有時(shí)都適用于其他技術(shù)。
在這里,有三個(gè)相互影響的術(shù)語:孤島、部分、漸進(jìn)。無論如何,主要思想是一樣的:需要將應(yīng)用程序的結(jié)構(gòu)分解成更小的塊,以使其加載更智能。
分區(qū)水合的作用
假設(shè)孤島架構(gòu)指的是靜態(tài)框架內(nèi)的Astro風(fēng)格的獨(dú)立交互塊。
可以說分解用戶界面(UI)的整個(gè)想法是部分水合,Astro孤島就是其中一個(gè)例子。但是要冒風(fēng)險(xiǎn),因?yàn)锳stro孤島已經(jīng)在那里。此外,部分水合似乎表明水合狀態(tài)不完全,這是一種誤導(dǎo)。
而漸進(jìn)式水合會(huì)引起與漸進(jìn)式網(wǎng)絡(luò)應(yīng)用程序(PWA)的混淆。也許分區(qū)水合作用是表達(dá)這個(gè)總體想法的一個(gè)很好的術(shù)語。
前端架構(gòu)的演進(jìn)
圍繞JavaScript前端架構(gòu)的活動(dòng)創(chuàng)建了一些最有趣的代碼工作。這是一個(gè)充滿激情的空間,他們正在探索新的概念領(lǐng)域,并進(jìn)行開創(chuàng)性的編程。他們以開放和協(xié)作的方式互動(dòng)和分享他們的想法。
其中包括RyanCarniato(Solid)和MiskoHevery(Qwik)。兩者都在采用最先進(jìn)的技術(shù),隨時(shí)向世界其他地方發(fā)布代碼和信息。
原文標(biāo)題:??Reactive JavaScript: The evolution of front-end architecture???,作者:Matthew Tyson?