Astro 的正式發佈給前端界帶來了什麼?
就在上週,Astro 團隊發佈了 1.0 的正式版本。
從年初我就開始關注這個項目了,但當時只是學習了一下倉庫的工程化搭建相關的東西 (changesets 自動發包之類),並沒有深入瞭解它本身的功能。藉着正式發版的機會,這幾天熟悉了一下 Astro 1.0,發現了很多有意思的地方,下文會分別從團隊背景、框架定位和核心優勢幾個維度給大家展開介紹,最後也會推薦一些學習資料。
團隊背景
在正式介紹 Astro 之前,先給大家聊一聊相關的背景。Astro 的作者是 Fred K. Schott
,沒錯,就是那個開發 Snowpack 的老哥,可以說是 Unbundle 構建工具的祖師爺:
但無奈的是 Vite 發展勢頭實在太猛,而 Snowpack 漸漸日薄西山,他本人也寫了文章發出下面的感慨:
文章鏈接: https://dev.to/fredkschott/5-more-things-i-learned-building-snowpack-to-20-000-stars-5dc9
大意就是 Snowpack 前途渺茫,用戶越來越少,感覺要做到頭了啦,而 Vite 發展的非常好,那後面開發的 Astro 就基於 Vite 來做吧。現在連 Snowpack 的官網都表示棄坑了,主動給 Vite 引流:
當然,除了 Snowpack,Fred K. Schott
的團隊 (叫Pika
) 還做了一件比較知名的產品: Skypack
,即 NPM 包的 ESM CDN 服務:
不幸的是,Skypack 也很長時間 (一年多) 沒有維護了,可以看出團隊也不再想繼續投入這個項目了,個人感覺主要有兩個原因:
-
競爭對手的強大。競品 esm.sh 一直在持續迭代且已經得到了 Deno 的官方推薦。
-
方案落地困難。此類 ESM CDN 應用到實際的業務項目中仍然有諸多的現實障礙,如請求數量多、不能 Tree Shaking、不能本地調試等等,要落地是一個比較難的問題,本人在 Bundle-less 的思考和實踐分享 一文中也有過專門的總結。
在近些年的時間裏,Fred K. Schott
團隊一直將重心放在了新項目 Astro 上面,經過 16 個月的打磨, Astro 在全球擁有了 30000 多個用戶,被 Google、Netlify 等大公司使用,Github 的 star 已經達到 15k +。
值得一提的是,Fred K. Schott
爲了這個項目專門成立了一個創業公司: The Astro Technology Company
,並且已經融到了 700 萬美刀
的種子輪投資,打算一直以開源的方式發展下去。相比於一些知名開源項目的贊助收入,如 Webpack[1] 22 w 刀 / 年、Babel[2] 30 w 刀 / 年,Astro 在經濟方面有如魚得水的優勢。
框架定位
接下來聊一聊 Astro 框架的定位,是像 Vue、React 這樣的底層渲染框架,還是像 Next.js 這種上層的研發框架?
這一點其實挺困擾初學者的,因爲 Astro 既自創了類似於.vue
、.jsx
文件的 .astro
語法,又提供了像 Next.js 裏面各種運行時的能力,比如約定式路由、構建優化、SSR 等等。
但實際上它給自己的定位非常清晰,即 content-focused
應用開發框架,換句話說,就是重內容、輕交互場景下的上層研發框架,比如大多數電商網站、文檔站、博客站、證券網站等等。
你可以將 Astro 理解爲一個垂直場景下的Next.js
,但它可以在它適用的領域裏面可以勝過其它所有競品 (如Next.js
、Remix
、Vuepress
等),這是它能夠做起來的重要原因。接下來,我們就來看看 Astro 的優勢在於哪些地方。
核心優勢
Astro 的主要優勢包括如下幾點:
-
Islands 架構,解決傳統 SSR/SSG 框架的全量 hydration 問題,做到儘可能少的 Client 端 JS 的開銷,甚至是 0 JS。
-
學習成本低。
.astro
語法和傳統的.jsx
和.vue
非常相似,對於新手前端來說也比較容易掌握。 -
使用靈活。對於頁面的開發,你既可以使用官方的
.astro
語法,也同樣可以使用.md
、.vue
、.jsx
語法,也就是說,你可以自由選擇其它前端框架的語法來開發,甚至可以在一個項目中同時寫 Vue 組件和 React 組件! -
構建迅速。底層構建體系基於 Vite 以及 Esbuild 實現,項目啓動速度非常快。
Islands 架構
在如上的幾個優點中,我們來重點說一說 Astro 的 Islands 架構,因爲這是它高性能最主要的原因。
Islands 架構模型早在 2019 年就被提出來了,並在 2011 年被 Preact 作者Json Miller
在 Islnads Architecture[3] 一文中得到推廣。這個模型主要用於 SSR (也包括 SSG) 應用,我們知道,在傳統的 SSR 應用中,服務端會給瀏覽器響應完整的 HTML 內容,並在 HTML 中注入一段完整的 JS 腳本用於完成事件的綁定,也就是完成 hydration (注水) 的過程。當注水的過程完成之後,頁面也才能真正地能夠進行交互。
那麼當應用的體積逐漸增大時,需要在客戶端執行的 JS 腳本也會越來越多,這也意味着 TTI(可交互時間) 指標越來越高:
爲了解決這個問題,Islands 架構將頁面拆分爲各自獨立的組件,包含靜態組件
和可交互組件
,如下圖的例子所示:
可以清楚的看到,一個頁面中只有部分的組件交互,那麼對於這些可交互的組件,我們可以並行地執行 hydration 過程,因爲組件之間是互相獨立的。
而對於靜態組件,即不可交互的組件,我們可以讓其不參與 hydration 過程,直接複用服務端下發的 HTML 內容。
可交互的組件就猶如整個頁面中的孤島 (Island),因此這種模式叫做 Islands 架構:
相比於傳統 SSR 中的全量 hydration,Islands 模式可以實現局部 (partial) hydration,從而優化 JS 的體積,減少網絡傳輸的成本和 JS 運行時的開銷。
在 Astro 中,默認所有的組件都是靜態組件,比如:
// index.astro
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent />
值得注意的是,這種寫法不會在瀏覽器添加任何的 JS 代碼。但有時我們需要在組件中綁定一些交互事件,那麼這時就需要激活孤島組件
了,在 Astro 如何來激活呢?其實很簡單,在使用組件時加上client:load
指令即可:
// index.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent client:load />
如此一來,Astro 會給瀏覽器傳輸一部分 JS 代碼供這個組件完成 hydration,以便後續的交互。
對比 Next.js 和 Remix
讀到這裏,你可能會說了,相比於其它的業界方案,Astro 到底優勢在哪裏呢?我們不妨來盤點一下。
首先是大名鼎鼎的 Next.js,我們知道 Next.js 是一個非常經典的 React SSR 框架,也是使用傳統的 SSR/SSG 技術,可以適用於幾乎所有的 Web 開發場景。而 Astro 在其適用的content-focused
場景下,性能會明顯高於 Next.js,以下是兩個真實的遷移案例:
可以看到,Astro 相比 Next.js 可以大幅度減少 JS 代碼的體積 (90% 以上),同時頁面的運行時性能也提升了 30% 以上。除此之外,Astro 不僅支持使用 React 框架,而且支持 Vue、Solid 等在內的各種前端框架,靈活性更高。
其次是最近比較火的新秀框架 Remix
,它基於 react-router 管理組件,通過 loader 和 action 的概念儘可能將邏輯代碼放到服務端的 bundle,從而減少客戶端 JS 的代碼體積,同樣是崇尚 0 JS 的理念,Remix 卻仍然需要全量 hydration,無法完成 partial hydration。此外,Astro 還有兩大優勢:
-
除了 React,也支持其它的衆多前端框架;
-
同時支持 SSR 和 SSG,而 Remix 不支持 SSG。
對比 React 18 的 Selection Hydration 特性
React 18 提供了 renderToPipeableStream
API,真正實現了 SSR 場景下的 Selection Hydration
,主要有如下的幾個特點:
-
在完整的 HTML 渲染之前就可以進行組件的 hydrate,而不用等待 HTML 的內容發送完畢
-
hydration 可中斷。比如頁面中有兩個組件: Sidebar 和 Comment,當這個部分的 HTML 發送至瀏覽器時,React 打算開始對 Sidebar 組件進行 hydrate:
如果用戶在這個過程中點擊了 Comment 組件,那麼 React 會中斷當前對於 SideBar 組件的 hydrate,從而去執行 Comment 組件的 hydrate:
詳情可見 React 18 SSR Architecture: https://github.com/reactwg/react-18/discussions/37
那麼 Astro 中的 Islands 架構,即 Partial Hydration
,和 React 的 Selection Hydration
到底是不是一個東西呢?
答案是否定的。兩者存在着非常大的區別:
-
從渲染框架上來看,
Selection Hydration
依附於具體框架的實現,而Partial Hydration
可以做到框架無關,即使是 Vue、Solid 的項目也可以做到Partial Hydration
。 -
從客戶端執行的 JS 總量來看,
Partial Hydration
可以做到加載部分組件的 JS 代碼,而Selection Hydration
仍然需要加載和執行全量的 JS 代碼。 -
從服務端和客戶端的交互來看,
Selection Hydration
嚴重依賴於流式 (Streaming) 渲染,服務端需要加上transfer-encoding: chunked
的響應頭,而Partial Hydration
沒有這個限制。
因此,雖然兩者都是在 Hydration 上做文章,但其實是兩種完全不同的方案,而且 Partial Hydration
更加通用,限制更少,執行的 JS 更少。
小結
以上就是對 Astro 的介紹和分析,後面有機會給大家剖析一下內部的源碼實現。文中如有不妥的地方,歡迎大家評論和指正。最後給大家推薦一些 Astro 的學習資料,方便大家讀完文章進一步瞭解:
-
Astro 官方文檔: https://astro.build/
-
Astro 實戰系列教程: https://aalam.in/blog/astro-get-up-and-running
-
歡迎
長按圖片加 ssh 爲好友
,我會第一時間和你分享前端行業趨勢,學習途徑等等。2022 陪你一起度過! -
參考資料
[1]
Webpack: https://opencollective.com/webpack
[2]
Babel: https://opencollective.com/babel
[3]
Islnads Architecture: https://jasonformat.com/islands-architecture/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/y9G_H8u09sbY4sYLRxgafw