從 Islands Architecture 看前端有多卷

大家好,我卡頌。

最近,Remix團(tuán)隊(duì)的暴躁老哥「Ryan Florence」一連懟了好幾個(gè)友商框架,比如:

噴SolidStart抄Remix的文檔

懟Next.js抄Remix的API設(shè)計(jì)

吐槽Astro、Qwik沒有什么新鮮理念

當(dāng)然,這些推文發(fā)出不到一天就被老哥刪了 ?? 。

我們今天不聊以上這些事兒的對錯(cuò)。

我想問問「不常關(guān)注前端新輪子發(fā)展的同學(xué)」,此時(shí)你們的內(nèi)心活動是不是:

這TM都是些啥框架?我咋一個(gè)都不認(rèn)識?
今天,我們從被「Ryan」吐槽的Astro的理念 —— Islands Architecture出發(fā),來看看前端到底有多卷。

Islands Architecture是什么
Islands Architecture(孤島架構(gòu))的概念最初是由「Etsy」的前端架構(gòu)師 「Katie Sylor-Miller」 在 2019 年提出,并由Preact作者「Jason Miller」在islands-architecture[1]一文中推廣。

這是一套基于SSR(服務(wù)端渲染)的架構(gòu)。要了解他的特點(diǎn),我們需要先了解傳統(tǒng)SSR的缺陷。

在傳統(tǒng)SSR中,首屏渲染時(shí),服務(wù)端會向?yàn)g覽器輸出HTML結(jié)構(gòu)。

當(dāng)瀏覽器渲染HTML后,再執(zhí)行前端框架的初始化邏輯,為HTML結(jié)構(gòu)綁定事件,這一步叫hydrate(注水)。

當(dāng)hydrate完成后,頁面才能響應(yīng)用戶交互。

也就是說,只有當(dāng)整個(gè)頁面所有組件hydrate完成后,頁面中任一組件才能響應(yīng)用戶交互。

Chrome LightHouse跑分中的TTI[2](Time to Interactive,可交互時(shí)間)指標(biāo)用于衡量「頁面變得完全可交互所需的時(shí)間」。


傳統(tǒng)SSR架構(gòu)的頁面隨著應(yīng)用體積變大,TTI指標(biāo)會持續(xù)走高。

孤島架構(gòu)的目的就是為了優(yōu)化SSR架構(gòu)下TTI指標(biāo)的問題。

在孤島架構(gòu)架構(gòu)下,組件分為:

交互組件

首屏不可交互組件

比如在如下頁面結(jié)構(gòu)中:


「首屏不可交互組件」包括Content、Advertisement、Footer(白色部分)

「交互組件」包括Header、Sliderbar、Image Carousel(彩色部分)

「首屏不可交互組件」會像傳統(tǒng)SSR一樣向?yàn)g覽器輸出HTML,而「交互組件」會在瀏覽器異步、并發(fā)渲染。

「交互組件」就像HTML海洋中的孤島,因此得名孤島架構(gòu)。


孤島架構(gòu)可以讓「交互優(yōu)先級較高的組件」優(yōu)先變得可交互,剩下的低優(yōu)組件再慢慢hydrate。

如此,在頁面hydrate完成前,重要的組件已經(jīng)可交互了,借此就能降低TTI指標(biāo)。

孤島架構(gòu)的現(xiàn)實(shí)意義在哪呢?比如,對于一個(gè)電商網(wǎng)站,顯然「立刻購買按鈕」的可交互性優(yōu)先級高于「反饋按鈕」的可交互性。

SSR讓用戶能夠更早看到頁面,孤島架構(gòu)讓頁面中重要的部分(立刻購買按鈕)可以更早被點(diǎn)擊。這背后,就是更高的購買率,更多的錢~~~

實(shí)現(xiàn)Islands Architecture的框架
在當(dāng)前,實(shí)現(xiàn)孤島架構(gòu)的全??蚣苤饕茿stro與Qwik。

Astro
Astro的特點(diǎn)是:作為全??蚣?,主要把控整體架構(gòu),對實(shí)現(xiàn)具體業(yè)務(wù)所需前端框架沒有要求。

也就是說,開發(fā)者可以在Astro中使用React、Vue、Preact、Svelte等框架實(shí)現(xiàn)具體業(yè)務(wù)邏輯,甚至是在一個(gè).astro組件中混用其他框架的組件。

比如,在下面例子中.astro組件中引入了React、Vue、Svelte三款框架的組件:


Qwik
Qwik的作者是builder.io的CTO 「mi?ko hevery」(同時(shí)也是Angular/AngularJS的發(fā)明者)。







mi?ko hevery
這款框架的特點(diǎn)是:超細(xì)粒度的孤島架構(gòu),且粒度是開發(fā)者可控的。

對于Astro,孤島架構(gòu)適用的對象是組件。而在Qwik中,孤島架構(gòu)最細(xì)的粒度是「組件中的某個(gè)方法」。

舉個(gè)例子,下面是HelloWorld組件(可以發(fā)現(xiàn),Qwik采用類似React的語法):


對應(yīng)頁面渲染效果:


打開瀏覽器Network面板,這個(gè)頁面會有多少JS請求呢?

由于這是個(gè)靜態(tài)的組件,沒有邏輯,所以答案是:沒有JS請求。

再來看看經(jīng)典的計(jì)數(shù)器Counter組件,相比HelloWorld,增加了「點(diǎn)擊按鈕狀態(tài)變化的邏輯」,代碼如下:


對應(yīng)頁面渲染效果:


打開瀏覽器Network面板,這個(gè)頁面會有多少JS請求呢?

答案還是:沒有JS請求。

注意這兩個(gè)組件的代碼中,定義組件使用的是component$,有個(gè)$符號。

在Counter中,onClick$回調(diào)也有個(gè)$符號。

在Qwik中,后綴帶$的函數(shù)都是「懶加載」的。

孤島架構(gòu)的粒度有多細(xì),就取決于$定義的多細(xì)。

比如在Counter中,onClick$帶$后綴,那么點(diǎn)擊回調(diào)是懶加載的,所以首屏渲染不會包含「點(diǎn)擊后的邏輯」對應(yīng)的JS代碼。

在點(diǎn)擊按鈕后,會發(fā)起2個(gè)JS請求,第一個(gè)請求返回的是「點(diǎn)擊后的邏輯」:


第2個(gè)JS請求返回的是「組件重新render的邏輯」:


這兩段代碼執(zhí)行后,Counter變?yōu)?。











審查元素會發(fā)現(xiàn),點(diǎn)擊前,button on:click屬性中保存了「邏輯所在的地址」:


點(diǎn)擊后,會從對應(yīng)地址下載JS代碼,執(zhí)行對應(yīng)邏輯。

React
為什么文章開頭暴躁老哥吐槽Astro、Qwik沒有什么新鮮理念呢,這是因?yàn)镽eact很早就在朝著孤島架構(gòu)的理念發(fā)展了。

在React中,這套理念被稱為Selective Hydration[3]。

具體來說,在SSR場景下,被Suspense組件包裹的組件會作為孤島架構(gòu)下的「交互組件」。

前端有多卷
雖然孤島架構(gòu)下的全??蚣苡斜姸嗪锰帲ㄊ灼龄秩究?、TTI短),但并不是萬能的。

他比較適合「對首屏渲染速度、TTI要求高,但整體頁面交互不復(fù)雜」的場景,比如:

電商頁面

博客

文檔

對于「重交互性」的Web應(yīng)用(比如「后臺管理系統(tǒng)」、「社區(qū)」),更適合傳統(tǒng)的SSR方案(比如Next.js)或CSR方案(直接使用前端框架)。

可見,孤島架構(gòu)的應(yīng)用場景并不大,但他的實(shí)現(xiàn)難度卻比CSR或傳統(tǒng)SSR高得多。

大部分開發(fā)者,究其一生可能都不會用到孤島架構(gòu)。

就是這么小的細(xì)分領(lǐng)域,都涌現(xiàn)了這么多競爭對手。

前端,真是太卷了......

參考資料

[1]
islands-architecture:
https://jasonformat.com/islands-architecture/
[2]
TTI:
https://web.dev/interactive/
[3]
Selective Hydration:
https://github.com/reactwg/react-18/discussions/37





作者:卡頌


歡迎關(guān)注微信公眾號 :魔術(shù)師卡頌