Skip to content

網站架構的演進

❤️

Shout out to Theo. He’s a cool guy, and I’ve learned a lot from him. In this article, I reference a lot of content from his YouTube video.

前端技術變動快速。過去我們使用多頁應用程式(Multi-Page Application, MPA)架構開發網站。而 React 的出現,讓我們可以透過客戶端的裝置來更新和渲染 HTML,也就是我們熟知的單頁應用程式(Single Page Application, SPA)。這使得我們在 client 端可以流暢地換頁,就像在使用 Native APP 一樣。然而,這背後也存在不少問題。因此,React 團隊在 React 18 中提供了 Server Components 功能,讓我們可以在 Server 端編寫能夠被渲染和被快取的 UI Component,從而解決部分性能和體驗上的問題。

但在開始前,我們需要先了解一下前端渲染技術從過去到現在的變遷,以及為什麼 SPA 會出現。接著,我們會討論 SPA 存在的問題,這些問題又是如何促使 SSR 的出現。

多頁應用程式 (MPA) 架構

最一開始我們的網站架構是透過後端渲染多頁的 HTML 來實現的。當 user 點擊某個連結時,我們會在後端處理這個連結,並且返回 HTML 文件。然後,用戶的瀏覽器就會自動把這個 HTML 文件載入到網頁中。網站架構如下:

單頁應用程式 (SPA) 架構

隨著 React 的出現,SPA 架構也逐漸被推行。它大大改善了 user 在網站中的瀏覽體驗。相對於 MPA,SPA 的網站可以更絲滑的換頁,網頁不會有換頁的閃爍。 並且這個架構可以讓網站的 client 和 server 端完全分離,當 server 出問題時,前端也可以有相對應的錯誤處理,我們也稱這個架構的渲染方式叫做客戶端渲染(Client-Side Rendering, CSR)。不過這種架構也有一些問題:

  1. 使用者的裝置有更多的工作要做。例如使用 JavaScript 來動態更新 HTML 的內容、管理使用者的 session 和頁面觀看權限等。
  2. HTML 的 Metadata 和內容需要透過 JavaScript 來更新,因此在 JavaScript 執行之前,搜尋引擎的爬蟲可能只會看到一個未渲染的頁面,這對 SEO 可能會造成不利影響。雖然現代的搜尋引擎 (例如 Google) 已經能夠處理並索引部分 JavaScript 生成的內容,但這並不保證所有內容都會被完全索引到。
  3. 單頁應用程式 (SPA) 的架構可能會比較佔記憶體,因為 SPA 通常在初次加載時需要加載大量的 JavaScript、CSS 和其他資源,並在客戶端維護應用的狀態。此外,長時間運行的背景任務和未正確釋放記憶體可能會導致記憶體流失,增加使用者裝置的負擔。
  4. 使用者需要透過大量的 API 來取得網站內容(動態或會過期的內容),這會導致後端需要產出大量的 Restful API,前端也需要在 Fetch API 時,需要做大量的錯誤處理。

當然,也有一些對應的解決方案。例如:

  1. 使用像 Next.js 的框架,透過部署的 web server 來處理權限、狀態管理、fetch 資料等事情移回 server 端。讓前端只要專注在客戶體驗有關的東西。
  2. 使用伺服器端渲染(SSR)確保搜尋引擎爬蟲能夠獲取到完整的頁面內容。
  3. 採用代碼分割 (Code Splitting)、懶加載 (Lazy Loading)、有效的狀態管理 (State Management) 和記憶體管理 (Memory Management),可以有效控制記憶體的使用,確保網站的效能和穩定性。
  4. 使用 GraphQL 提高 API 數據查詢的效率和靈活性。

講了這麼多,讓我們來看一下 SPA 架構長什麼樣子吧!

Server Side Rendering (SSR) 架構

Full Page SSR

Full Page SSR 是指 HTML 在 server 端生成和渲染的行為。整頁的 HTML 被生成後才傳送到瀏覽器。相對 SPA 架構,後者是將 HTML、CSS、JavaScript 傳送到 client 端,並在 client 端執行 JavaScript 來生成和渲染內容。這裡間單列出幾個優缺點:

優點

  1. SEO 友好:由於搜索引擎爬蟲可以直接看到完整的 HTML,因此更利於 SEO。
  2. 首屏(不需捲動網站位置)加載速度快:因為伺服器生成了完整的 HTML,瀏覽器在收到後可以立即顯示頁面,提升了首屏加載速度和用戶體驗。
  3. 較好的兼容性:不依賴於客戶端的 JavaScript 執行環境,因此在某些較舊的或限制 JavaScript 的瀏覽器中也能正常工作。
  4. 不需要像 SPA 一樣,在一開始要解析大量的 JavaScript 程式碼。當然 JavaScript bundle size 也會相對 SPA 小很多。

缺點

  1. 伺服器負載較高:伺服器需要承擔更多的渲染工作,可能會增加伺服器的負載。
  2. 響應時間可能較長:伺服器端渲染需要完成數據處理和 HTML 生成,這可能會增加網站的響應時間。
  3. 開發複雜度:需要處理伺服器端和客戶端的混合邏輯,增加了開發的複雜度。

我們看一下 Full Page SSR 的架構:

值得一提的是,在頁面完成 Hydration (Browser Rendering 其中的一個階段) 後,你是可以透過 API 取得網站資料來再更新 UI 的顯示的,而不需要進行頁面刷新。但如果是多頁應用 (MPA) 就需要了。不過這個架構因爲 server component 的誕生(React 18) 變得更加強大。讓我們來看一下 server component 的引入會如何改變 SSR 的架構吧!

引入 server component 的 SSR: 透過 Suspense 實現 Streaming Server Rendering

大家想像一下前面所提的 Full Page SSR ,該架構是以整頁為單位做伺服器的渲染。如果個別的 component 也能進行獨立的伺服器渲染。我們是不是可以取代傳送整頁的 HTML,將渲染好的 component 透過 streaming 的方式傳送給 client 端。從而降低網站響應時間呢!再來,我們更進一步思考這個問題。如果 component 是可以在伺服器渲染的,那我們是不是可以透過拆分 component,將靜態(不會改變的)component,預先渲染好,並 cache 住。以後只要 client 端要用到的 component 就可以直接從 cache 中取得。這樣不只可以解決網站響應時間較長的問題,連伺服器負載問題也能同步降低。而這當中最關鍵的就是 server component 的出現。它讓這一切得以實現。最後我們來看一下引入 server component 的 streaming 渲染架構吧~也非常推薦看這個影片

Reference

© 2024 Eric Tsai