稍有經驗的開發者,可能對最近 SPA,SSR 等術語不太陌生,大概也能知道 SPA 指的是單頁式應用(Single Page Application)、SSR 是伺服器渲染(Server-Side Rendering);可是仔細想想,在前端整個興起之前,主流的 PHP、JSP 不也是伺服器渲染嗎?中間發生了什麼?現在的開發者又為什麼開始想走回 SSR 了呢?
今天就讓我們一起來了解在那些專有名詞的背後,有著什麼時空背景及技術限制吧。
本系列文已經重新編校彙整編輯成冊,並正式出版囉!
《前端三十:從 HTML 到瀏覽器渲染的前端開發者必備心法》好評販售中!
喜歡我文章內容的讀者們,歡迎您 前往購買 支持!
筆者我剛進入相關領域時寫的是 JSP(Java Server Pages),基本語法跟原生的 ASP、PHP 有點像,藉由 <%
& %>
標出 Java 程式的範圍,後端進行編譯、運算後,再將處理好的 .jsp
檔回給前端;而與使用者的的互動則透過 jQuery 控制。因此那時所撰寫的程式經常會在同一隻 .jsp
檔,內容混合著 Java 及 JavaScript 的程式,再加上透過 jQuery 動態操縱 DOM 及 CSS,可以說是真正的 義大利麵程式碼。
於是一些開發者就開始嘗試,將資料與 UI 分離,再撰寫控制器去操縱、計算這兩者,也就是俗稱的 MVC 架構。MVC 為三個字的縮寫,分別代表:
圖片來自 Huli 的 前後端分離與 SPA
藉由這樣權責分明的設計,糾纏混亂的義大利麵變成了各自獨立的 義大利餃,程式的整體架構也得以被這樣的設計梳理整齊。
MVC 帶來了更低的耦合度,更高的可維護性,並且讓專案能被完整的分工,這樣的概念得到開發者的喜愛,最著名的大概是幾年前熱門的 RoR 吧?當然其他各大語言也都有包含此概念的框架被實作出來,開發者可以輕易的挑選到合適自己的 MVC 框架,並快速架構出網站伺服器的雛形。透過 MVC 架構,也算是讓 SSR 的網站程式有個相對理想的程式架構參照。
但有幾個 SSR 的問題,是單靠 MVC 框架無法解決的:
這些問題的解決方案,在 Gmail 問世之後出現了一線曙光。
Gmail 就是 Google 出的電子信箱服務,相信應該不少人都有公司或私人的 Gmail 信箱;在 2004 年問世以來,便一直是熱門好用的免費信箱選擇;那為什麼要特別提到它呢?
因為 Gmail 充分利用了瀏覽器的 XMLHttpRequest,透過這個 API 送出新的 Request,取得更多資料,再透過 JavaScript 變更目前畫面上的內容,過程中畫面完全不需要重新渲染,也就不會出現惱人的一片白,整體的使用者體驗好棒棒!
透過 XMLHttpRequest,前述的兩個問題都不會是問題。伺服器只需要提供一個引入其他 JavaScript 的頁面,其他的頁面流轉、資料獲取、DOM 調整,全部交給 JavaScript 處理,除了降低伺服器的運算效能消耗及資料吞吐量,還讓網站使用者使用網站有如使用獨立的應用程式一樣流暢,單頁式應用(Single Page Application,SPA)也因而得名。
由於 SPA 的出現,伺服器端也就不用再處理 MVC 中 View 的部分,而是交給前端來處理,但這樣一來前端要處理的事情就包山包海了,取得資料、處理畫面、頁面跳轉,儼然有種要變成義大利麵程式碼的跡象。
聞到 壞味道 了,開發者當然不能讓這樣的事情發生;既然 MVC 的架構能有效管理程式碼,那麼就把 MVC 的概念搬到前端來吧!
圖片同樣來自 Huli 的 前後端分離與 SPA
後端沒有自己的 View,那麼就只需要提供資料給前端的 Model,讓前端完成自己的 MVC;回頭看一下 昨天 提到的 Awesome Javascript - Framework,其實分類是 MVC Framework,前端 MVC 的程式架構已經是一個非常普遍的方向,不過實際上各家的實作、稱呼不見得是 MVC,但同樣都會有管理資料取得、加工處理的 Model,以及負責處理畫面細節的 View。
SPA 成為新共主,如同 昨天 提到的,大量的前端框架不斷湧現,箇中實作也是互有巧妙,但同樣都是藉由 JavaScript 處理大部分的事情,提高使用者體驗。
但看似美好的 SPA 也不是沒有任何缺陷,由於需要仰賴前端下載大量 JavaScript 檔案,隨後才計算、渲染畫面,造成第一畫面需要較長的反應時間,在性能較差的行動裝置上更是如此;除此之外,也因為伺服器僅提供載入 JavaScript 的空殼 HTML,SEO(Search Engine Optimization) 更是慘不忍睹。
剛好這些缺點,都是原本 SSR 的網頁中不存在的問題,但 SSR 網頁的伺服器負荷、使用者體驗也是爛到笑... 要是可以摻在一起 做成撒尿牛丸 就好了。
好,那就摻在一起吧!
既然 SPA 的問題只在第一畫面,那就在伺服器先算好第一畫面,其他畫面再透過 JavaScript 動態處理;也就是第一畫面為 SSR,其他畫面是 CSR(Client-Side Rendering),這樣是不是就完美了呢?
這樣做的代價,就是同一個頁面需要實作兩次顯示邏輯(前端後端各一次);幸好 JavaScript 不是一個純粹前端的語言,後端可以跑在 Node.js 中,開發者得以使用大致相同的程式,實現這樣的需求;這種同一份 JavaScript Code 可以跑在前端與後端的程式設計,叫做 Isomorphic JavaScript,同構的 JS。
也有人叫做 Universal JavaScript,通用的 JS。
在這樣的概念出來後,前端框架的 SSR 框架也就應運而生了,例如 React 的 Next,及 Vue 的 Nuxt,都是原本前端框架的語法再擴充,讓原先就熟悉框架的開發者,只需要越過相對小的進入門檻,就能滿足第一頁 SSR 的需求。
除了透過 SSR 框架幫你把頁面的第一次渲染即時算出來,在一些資料相對簡單,變動不太大的網站,也可以選擇透過例如 Prerender 之類的工具,是先把網頁全部算好,儲存成靜態頁面,這樣也可以解決 SEO 的問題。
藉由 Isomorphic JavaScript 的設計,及 Prerender 等工具,第一畫面才會出現的問題就能被解決,關於 SPA 及 SSR 的優缺點取捨,自然也就再也不是問題。
沒錯,小朋友才做選擇;我全都要!
關於更多 SPA 渲染的技術選擇,推薦大家可以參考 Google - Rendering on the Web,無論是 SEO 的影響,或是解決方案選型,文中都描述、整理得非常清楚!
這兩天講了非常多技術名詞,希望讀者沒有被這堆名詞嚇到。如同 良葛格在這篇文章 中提到的:「程式開發是一個隨意創造、濫用名詞的世界」;技術名詞多如牛毛,甚至同一個名詞在不同場景也常有著不同意思,若過度糾結於名詞的定義,造成無法溝通協作,就真的是本末倒置了。唯有開發者清楚知道自己想要、需要什麼,並理解名詞、工具、方法論背後的動機意涵,才能在這個稍嫌混亂的世界裡,找出最適合自己的解決方案,走出一條精彩的路。
以上就是今天的文章啦,希望有幫助到讀者您;如果文中有任何想法或有不清楚的地方,都歡迎您一起回應討論,一起成為更好的前端工程師吧!
筆者
Gary
半路出家網站工程師;半生熟的前端加上一點點的後端。
喜歡音樂,喜歡學習、分享,也喜歡當個遊戲宅。相信一切安排都是最好的路。