淺談 SPA、CSR、SSR、MPA、SSG 專有名詞

前言

這一篇稍微聊一下這幾個專有名詞個別代表的意思是什麼,畢竟是一個很常見的東西,當若你能夠提得出差異,那麼你在面試時就會有相當大的幫助。

SSR(Server Side Render) 與 MPA (Multi-Page Application)

第一個我想先聊聊什麼是 SSR,SSR 全名是 Server Side Render,中文名稱是伺服器渲染,伺服器渲染的意思是什麼呢?

舉例來講你是正在要開啟瀏覽器,這邊不管你是要開 Google Chrome、Firefox、Edge (微軟新的瀏覽器)、即將消失的 Internet Explorer (或者這時候看文章已經滅絕 IE 的你)又或者是即將有潛力成為下一代 IE 的 Safari 通通隨便你(被揍),當你開啟在瀏覽器輸入一個網址 or 透過我的最愛進入任何一個網址時,這個過程中我們的瀏覽器會透過網路發送一個請求 (Request) 給伺服器跟伺服器說你要進入哪一個頁面,例如你現在要進入網站的首頁,所以伺服器收到這個需求之後就會回傳 or 回應 (response) 你要的畫面給瀏覽器,然後瀏覽器再去依照伺服器給的東西來去呈現畫面給你。

這一段我們可以用比較生活化的方式描述這個一整個流程,首先我們先描述一下身份的代表:

  • 使用者 - 我
  • 瀏覽器 - 一張白紙
  • 網路 - 郵差
  • 伺服器 - 畫家

情境概念類似(這邊有稍微省略一些,主要是為了好理解):

今天我(使用者)想要看哥吉拉的描述,但是這邊畫家很窮,每一次想看什麼,我都必須提供一張白紙,並附上一張信件的內容 (Request) 描述,舉例來講:

1
畫家你好,我希望可以請你幫忙準備畫一張哥吉拉的畫像。

接下來我們就會請帥氣郵差先生/小姐(網路)幫我們將信件內容交給畫家(伺服器),接下來畫家就會依據我們信件內容開始準備畫筆並在我們一起寄給他的白紙繪畫上哥吉拉的畫像,最後繪畫完畢之後,畫家會再請郵差將畫好的繪畫一起寄回去給我來觀看。

而這也是一般的傳統開發模式,為什麼這樣說呢?當然與後面要聊的東西有關係,在傳統的開發上這又稱之為 MPA (Multi-Page Application) 也就是多頁式應用程式,通常一個頁面會搭配一個 HTML 檔案,所以你可以看到上面的模擬情境描述中,如果我們想要請求任何一個新的畫面都必須重新提供一張白紙給畫家,因此這個過程中,當我們切換畫面就會發生一種狀況,會有一瞬間的畫面空白,而這一段也會導致使用者必須等待畫家畫完,在現今社會步伐較快的情況下,若你畫面超過一定秒數才出現的話,使用者是會跑掉的,對於一個電商網站來講這是一個非常傷的一件事情,除此之外在效能上也會比較差,畢竟所有頁面都是由伺服器來處理,當然這還不包含每一頁可能都有自己的 CSS、JavaScript 檔案要下載。

如果你有寫過後端的話,這邊舉例 Express 通常會搭配 EJS 內容,但這邊舉例用另一個樣版引擎 pug 當作示範:

1
2
3
4
5
extends layout

block content
.container
h1= title

透過後端處理完之後就會渲染成一個正常常見的 HTML 結構

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<title>這只是首頁</title>
</head>
<body>
<div class="container">
<h1>這只是首頁</h1>
</div>
</body>
</html>

畢竟瀏覽器只看得懂 JavaScript、HTML 與 CSS,所以這一段就必須透過後端處理完之後再將這個 HTML 與相對應的 CSS 以及 JavaScript 吐給使用者的瀏覽器來渲染畫面,因此 SSR 通常必須處理資料與畫面。

CSR(Client Side Render) 與 SPA (Single-page Application)

那麼接下來我們來聊聊 CSR,如果你有在使用 Vue、React 或者是 Angular,預設上都是走 CSR 的,而 CSR 是什麼意思呢?CSR 絕對不是你直接丟上 Google 出現的這個單字「企業社會責任(Corporate Social Responsibility 簡稱CSR」,正確全名是 Client Side Render,中文名稱叫做客戶端渲染,相信看到客戶端渲染應該會覺得很模糊混淆,你可以把它想像成瀏覽器渲染的概念,雖然這樣講是有點錯誤的,但是在理解上會比較好理解,但是正確來講還是會建議理解上是客戶端渲染會比較好。

在前面我們有聊到 SSR 會透過伺服器來渲染畫面給使用者觀看,而 CSR 則是反過來,而是變成透過使用者的瀏覽器去渲染畫面,這一段就不再經過伺服器了。

那…伺服器這時候要幹嘛?因為 CSR 的關係,伺服器就可以比較單純一點,純粹做一些邏輯與資料處理給使用者就好,然後透過使用者的瀏覽器自己去處理畫面,通常來講後端就只需要丟 JSON 給使用者的瀏覽器處理就好,例如:

(資料來源:https://github.com/hexschool/w3hexschool-API)

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"keyID": 0,
"blogList": [ // 文章列表
{
"title": "PixiJS V5 教學 (0)", // 文章標題
"url": "https://israynotarray.com/javascript/20200203/3949702627/" // 文章 URL
},
...
],
"updateTime": "2020/2/18 下午 7:49:36", // 表單更新時間
"blogUrl": "https://israynotarray.com/", // 部落格網址
"name": "Ray" // 若有勾選願意公開暱稱則會顯示暱稱
}

與前面的 SSR 模式相較之下,伺服器就可以少處理畫面這一段,而單純的純粹處理資料給使用者就好。

這邊我們也一樣用生活化的舉例來舉例 CSR,一樣這邊先舉例身份:

  • 使用者 - 我
  • 瀏覽器 - 一張白紙
  • 網路 - 郵差
  • 伺服器 - 畫家

情境概念類似(這邊一樣有稍微省略一些,主要是為了好理解):

今天我(使用者)想要看哥吉拉的描述,但是這個時候因為時代進步了!所以我們不再使用白紙,而是使用一個畫家準備好的電子版,這時候當然我們依然會需要寫信跟郵差說我們要什麼畫面:

1
畫家你好,我希望可以請你幫忙準備畫一張哥吉拉的畫像。

這時候郵差將信件寄信給畫家後,畫家這時候竟然不用開始繪畫,而是在寫一封信內容是:

1
你幫我點一下電子版上的某處就可以看到了。

接下來我收到信之後,依據這份資料照做一次,確實畫面就出來了。

有發現嗎?我們流程上畫家完全少了繪畫這一段,而是透過畫家已經準備好的電子版,只要依照他提供的操作我們點一點就可以看到我們要的畫面了,是不是使用者體驗上不但好又快,畢竟不用多等畫家繪畫。

那麼 CSR 通常是在講 SPA (Single-page Application)居多,而 SPA 又稱為單一頁面應用程式,通常我們在操作的畫面只會有一個,就如同前面所講的電子版一樣,我們從頭到尾都在同一個板子上,而不會因為我們要看其他畫面,而必須一直提供新的白紙給畫家,在 CSR 的狀況下,效能會比 SSR 好上許多,為什麼呢?因為 CSR 的效能主要來自使用者身上,所以對於伺服器的負擔也會降低很多,你可以試著思考一下在原本的 SSR 開發下上,當只有你一個人請求畫面時覺得沒有什麼差別可能很快,但是當有上千上萬的人同時跟伺服器要畫面,這時候效能是不是就會變差了?畢竟所有的效能與資料處理都在伺服器上。

反之今天 CSR 是變成我們將畫面的處理交給的使用者,也就是使用者的瀏覽器上,因此每一個人的效能都是依據自己的電腦來決定(現今個人電腦效能都非常強大),所以對於伺服器的負擔就會降低很多,而且切換頁面上也會非常快速,這個過程中就會透過一個技術叫做 AJAX(Asynchronous JavaScript and XML) 來跟後端請求資料 or 資源,但這不是這一篇要介紹的。

因此畫面的呈現通通交由給使用者後,伺服器就可以專心處理資料,在效能上就會非常的強大,但是可能會有首次進入網頁畫面時會稍微比較慢的問題發生,畢竟 CSR 的模式下通常是使用了 JavaScript 來處理畫面的渲染,因此可能這個 JavaScript 的檔案就會特別大,變成使用者要先下載 JavaScript 的檔案,當下載完成之後每一次切換上就會非常快速且流暢,剛剛也有講到 CSR 大多都是在講 SPA,因此在 SPA 開發模式下,通常我們都一直固定在同一個頁面,可能都是在 index.html 底下,然後透過模擬後端路由切換的模式達到切換頁面的感覺,比較常見在 Url 後面會加上一個 「#」字號,例如首頁切換到其他頁面:

1
https://israynotarray.com/w3cHexSchool-Search/#/ -> https://israynotarray.com/w3cHexSchool-Search/#/user

而這一段實際上我們都依然是在 index.html 下,只是透過 JavaScript 與 Client 來處理這一段。

那 CSR 就完全沒有缺點嗎?當然也是有,如果你是作為一個內容網站的話,其實對於搜尋引擎是非常差的,畢竟所有的畫面都是透過使用者的瀏覽器去渲染與後端的渲染模式不同,後端再給你畫面時會是已經渲染完畢的靜態頁面檔案,而 CSR 則是透過 JavaScript 後來才渲染的,而這又稱之為動態頁面檔案,因此在 SEO 就會比較差。

可是目前來講 Google 已經有說明他們的搜尋引擎都已經開始陸續支援 SPA 的模式,所以 SPA 的劣勢也開始越來越低,而前後端開發上也會更聚焦於各自的工作上。

辨別網站是 SSR 還是 CSR

基本上 CSR 是比較好辨別的,最簡單的辨別方式就是點瀏覽器的「檢視原始碼」

我是用 Firefox

接下來如果你原本的畫面是這樣子,非常的豐富:

六角全馬鐵人搜尋器

但當你查看檢視原始碼後,卻只有一下這樣子的話,代表這個網頁採用的 CSR 模式:

CSR

除此之外,通常 CSR 就是在講 SPA 所以都會出現這兩個標籤

1
<noscript><strong>We're sorry but w3hexschool-search-ts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>

不然就是中間只有一個元素:

1
<div id="app"></div>

但是如果你回到前面改用網頁開發者工具來看 <div id="app"></div> 這一段的話,卻會發現內容相當多

CSR

這就代表著,這是一個 CSR 網頁。

反之若檢視原始碼的話,可以與網頁開發者工具看到的內容相同就「基本上」是 SSR,但這一段無法保證一定是,你如果現在在我的部落格點右鍵檢視原始碼的話,可能會看到與我畫面上結構相同的元素,那這樣算 SSR 嗎?實際上不算,因為我的部落格並沒有與後端合作,純粹只是一個靜態網站(這一個靜態網站我們下次再聊),所以我這邊才會說 SSR 辨別上可能沒辦法很準確的辨別,但是 CSR 上會比較好辨別。

就結論來講該選 CSR 還是 SSR 其實各有優缺點,雖然看似 CSR 比較好,而且效能問題主要在使用者身上,因此就會有一句話是「如果你想幫公司省錢的話,就選擇 CSR」(誤),但實際開發上還是要看專案為主,畢竟有些網站注重的不是使用者體驗,而是 SEO 的排名。

你可能會說「難道不可以 CSR 然後 SEO 強大的嗎?」,基本上也是可以解決的,有許多技術都有提出解決的方式,可是這邊我們不探討這個,那 SSR 呢?難道不能效能好嗎?當然可以,有錢萬事搞定(笑)。

SSG(Static Site Generation)

前面分享了 SSR 與 CSR 的觀念後,你可能還聽過 SSG(以下都會簡稱 SSG),那什麼是 SSG 呢?

SSG 有兩種解釋:

  • Static Site Generation
    • 靜態頁面生成
  • Server Side Generation
    • 伺服器生成

名詞上看似不同,但是這兩者生成的東西都是相同的,也就是生成一個「靜態頁面」。

為什麼要提到 SSG 呢?最主要原因是 CSR 模式會有 SEO 問題,雖然前面有說到 Google 已經有針對他們搜尋引擎支援 SPA 開發的頁面,但 SSR 模式的網頁還是會有一定的 SEO 趨勢,畢竟所有資料都是直接從伺服器渲染而非 JavaScript 動態渲染。

那這種狀況下我們可能會為了 SEO 拋棄 SPA 嗎?不,很難,畢竟 SPA 的出現就是為了解決使用者體驗的問題,拋棄它的話不就本末倒置了?因此就誕生了一些為了解決 SEO 問題的框架,例如:Nuxt.js(Vue)、Next.js(React)。

而 SSG 的概念會將你原本 CSR 只有一行標籤的狀況:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

變成類似 SSR 的狀況,你可以看到一大推的文字與 HTML 真實的寫原本 #app 標籤內:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<header>Ray</header>
<ul>
<li>這是一段話</li>
<li>這是一段話</li>
<li>這是一段話</li>
<li>這是一段話</li>
</ul>
<footer>這是 footer</footer>
</div>
</body>
</html>

而這一整個運作的概念簡單來講來講就是,在編譯時這些框架(Nuxt.js、Next.js 等),會先依據你的 AJAX 內容先跟遠端伺服器請求第一次的初始資料,然後再將這些資料真實的寫入到畫面上,進而生成 HTML 檔案,因此當你「檢視畫面原始碼」時,是會非常非常到豐富,而不是只看到 #app 標籤。

所以前面才會說「辨別網站是 SSR 還是 CSR」的這個方式只是一個參考方式,實際上還是要搭配一些工具來辨別哩。

參考文獻