--- tags: FrontEnd --- # How Morden App Render > CSR is Dead 這句話並不是跨大其詞,在 2022 年,前端推陳出新了許多 meta framework,例如 - [next.js](https://nextjs.org/docs/getting-started) - [svelte kit](https://kit.svelte.dev/) - [qwik.js](https://qwik.builder.io/) - [solid.js](https://www.solidjs.com/tutorial/introduction_basics) - [astro.js](https://docs.astro.build/en/getting-started/) - [deno.js](https://deno.land/manual@v1.30.3/introduction) > meta framework 就是泛指在 framework 之上,還解決了 routing, SEO, data-fetching 相關問題的 framework,詳情可以看[這篇文章](https://hackmd.io/@ChrisW/r19iRgaho), > 為了容易理解,這邊先簡單的將 SSR 與 Meta Framework 劃上等號 這些新框架解決了大部分 SSR 之前會被詬病的問題,並繼承了 SSR 以往的優點: - 第一頁 rendr 快速 (FCP) - 具有 SEO - 流暢的互動(不會有瞬間白畫面) - clien 負擔較小 以上總總原因讓 SSR 逐漸與 CSR 可以站在同一個跑道競爭,而其中大功臣就不得不提到 Hydration 這個步驟。 ## Hydration  > 來自 [Qwik Doc: introducing-resumability](https://qwik.builder.io/docs/concepts/resumable/#introducing-resumability) Hydration 最主要的動作就是在 server 生成好的 HTML 上面加入 event handler,這樣才能在互動之後,做出對應的改變,步驟是這樣的: 1. 在 server 產生 HTML,並下載 2. 拿取這個頁面需要的 JS file 3. 在 client 組裝 HTML 和 JS,後續的 render 也繼續在 client 進行 也是因此,現代的 SSR 才能兼顧 FCP、SEO 和流暢的使用者體驗 但因為在第一次需要下載大量資源,又會造成另一個問題,那就是 TTI 過長。 > TTI (time to interactive,使用者可以跟頁面互動的時間點) 而為了解決 Hydration 帶來的問題,有很多框架都給出了自己的答案。 ## Solation 1: Qwik - Resumability  > 來自 [Qwik Doc: introducing-resumability](https://qwik.builder.io/docs/concepts/resumable/#introducing-resumability) >Resumability is about pausing execution in the server and resuming execution in the client without having to replay and download all of the application logic. 接續性( Resumability ) 的意思是: Qwik 可以在 server 暫停執行後,直接在 client 接續執行,但不需要下載任何 js file 或執行任何 APP 邏輯,包含掛載 listener、加載狀態 (aka hydration)。 Qwik 之所以可以做到這點最大的原因在於序列化( serialize )。 ### Serialize 序列化(Serialize)在使用 hydration 技術的 SSR 框架中也時常被使用到 作用在於將裝態包裝成 json 或是任何一個可恢復 / 可取用的格式,鑲入在 ``<script>`` 中,這樣可以幫助 client side 更快的 render。  > 來自: [rendering on the web](https://web.dev/rendering-on-the-web/#a-rehydration-problem:-one-app-for-the-price-of-two) 而 Qwik 將序列化作用在三個地方 - listeners - component tree - application state Qwik 會將序列化後的 eventhandler 掛在 dom 元件的 attritube 上。 ``` <button on:click="./chunk.js#handler_symbol">click me</button> ``` 這個元件被觸發,qwik 就只會下載這個按鈕相關的 js file。 當狀態改變時,Qwik 會在 SSR 就對 DOM 的狀態做序列化,這樣等下次需要時,就能夠快速用這個序列化資料生成 HTML 如此一來就能達到在 client side 0 hydration 的效果了。 但需要注意的是,要使用 Qwik 的這種方式,可能會跟傳統的 parent-child 撰寫方式會有很大的不同。 每個 component 之間必須要不能互相依賴,或是都可以採用 Dependency inject 的方式。 延伸閱讀:[Qwik doc](https://qwik.builder.io/docs/concepts/resumable/#introducing-resumability)、[保哥原理介紹](https://www.youtube.com/watch?v=bU6KeelyRfc&t=3105s) ## Solation 2: Astro - Island Architecture  Islands Architecture 最早是在 2019 由 Katie Sylor-Miller 提出的,並由 Preact 的創建者 Jason Miller 透過[文章](https://jasonformat.com/islands-architecture/)擴展。 原理是把每個需要用到JS的元件獨立出來,變得像是獨立的插件一樣可以放到你靜態網站的任何一個地方。 而要讓這些 component 之間的 render 進程不受影響,就必須要提到 Partial Hydration。 > Partial Hydration 是針對部分的 component 做出 hydration,只對需要 render 的部分發送請求並下載 js file  套用到上面的 Islands Architecture 來說,每個 component 都有自己的 Hydration ,每一個 Hydration render 獨立於頁面上的任何其他 render,也因此才能做到彼此不會互相影響。 Astro 在預設情況下可以達到 0 js file,更可以在任何一個 astro 頁面下使用 React, Preact, Svelte, Vue, SolidJS, AlpineJS 等 ui library ### How it's work in Astro 接著我們來看一下 astro 實際上是怎麼運作的 Astro 將 元件分成 - 動態交互元件 - 靜態元件 但既然同時存在動態與靜態元件那server side生成的時候該怎麼去做分別呢 先看看以下的 astro 搭配 react 的範例: ``` // src/pages/index.astro --- // Example: Use a dynamic React component on the page. import MyReactComponent from '../components/MyReactComponent.jsx'; --- <!-- This component is now interactive on the page! The rest of your website remains static and zero JS. --> <MyReactComponent client:load /> ``` 在 component 元件上的 attribute `client:load` 是[client 指令](https://docs.astro.build/en/reference/directives-reference/#client-directives),告知 astro 該 componey 使用動態還是靜態元件呈現。 同時,在實作Islands Architecture的框架會透過『占位符』(placeholders/slots)的方式預先留好插入動態元件的地方接著在clien-side各別同時做partial hydration。 ### 關於 astro 小結 總結 Island Architecture其實就是結合不同的前端技術所建構出來的設計模式(SSR + SSG + Partial Hydration + slot/placeholder) 1. 繼承大多數 SSR + SSG 的優點,減少非常多無謂 js 載入,也解決的 TTI 過高的主要問題。 2. 如果是 component 之間需要大量的互動,那有關於獨立 component 彼此之間交流就會是一大問題。 3. 還是適用於以靜態內容為主的網站。 ## 其他 render 方式 其實還有其他解決 TTI 的方式,但礙於篇幅就先稍微點到一下就好 - [streaming](https://www.patterns.dev/posts/ssr/) - [SSG](https://www.patterns.dev/posts/incremental-static-rendering/) streaming 指的是一邊產生許多小片段的 HTML,一邊回傳給使用者,瀏覽器可以更早收到 HTML 的小片段,更早開始執行瀏覽器的渲染工作。這可以改善 TTFB, FCP。 SSG 就是指 static site generate: - pre-render - 所有已知的 page 都被 render ( no dynamic router) - server cost 超大 ## REF https://www.quora.com/Why-is-React-a-library-and-not-a-framework https://www.ombulabs.com/blog/javascript/what-is-a-javascript-meta-framework.html https://kayshih.com/posts/islands-architecture https://docs.astro.build/en/concepts/islands/#what-is-an-astro-island https://www.youtube.com/watch?v=bU6KeelyRfc&t=2640s https://www.patterns.dev/posts/#design-patterns https://www.youtube.com/watch?v=cLivMMSeFgE https://www.builder.io/blog/hydration-is-pure-overhead https://qwik.builder.io/docs/concepts/resumable/#resumable-vs-hydration https://shubo.io/rendering-patterns/#ssr-with-hydration https://dev.to/this-is-learning/why-efficient-hydration-in-javascript-frameworks-is-so-challenging-1ca3 https://www.youtube.com/watch?v=x2eF3YLiNhY
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.