iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
Modern Web

不只懂 Vue 語法:Vue.js 觀念篇系列 第 3

不只懂 Vue 語法:以 Vue 和 Nuxt 為例,說明 SPA 和 SSR 的概念?

  • 分享至 

  • xImage
  •  

問題回答

Vue 是 SPA 框架,而 Nuxt 是 Vue 生態系裏的一個能同時實現 SPA 和 SSR 的框架。SPA 的主要技術是不用重刷頁面來更新頁面內容,而是透過切換元件來達成切換頁面的效果,提升瀏覽時的流暢度,但最大缺點是不利於 SEO。

SSR 模式是較傳統的方式,在 SPA 還沒流行時主要是用 SSR,意思就是所有內容都在伺服器準備好,再把完整的 HTML 檔案傳到前端,前端只需顯示它就行了。但最大缺點是,每次跳轉頁面都要重新向伺服器發出請求,並重刷頁面,瀏覽流暢度明顯不及 SPA。但好處是有利 SEO,因為搜尋引擎能直接爬到在 HTML 上的內容。

相反,Nuxt 是一個同時能結合 SSR 和 SPA 的框架,目的是解決以上提到的 SEO 問題。在首次載入頁面時,用戶端向伺服器發出請求。伺服器會回傳兩種檔案,一是完整的 HTML 檔案,二是跑 SPA 模式時會用到的檔案。因此,在剛載入第一頁時,我們是使用 SSR 模式,即是從伺服器端把所有內容都處理好,直接把 HTML 塞回前端。之後,當用戶與網頁互動時,就會跑 SPA 模式。

以下會再詳細解說這些概念。

以 Vue 為例,到底什麼是 SPA?

  • 切換頁面其實就是切換元件
  • 使用 AJAX 非同步遠端取資料的方式,更新部分畫面
  • 在客戶端把內容從 JavaScript 檔案渲染在畫面上

切換頁面其實就是切換元件

用 Vue 為例子,即使我們打開不同網頁,但由始至終我們仍然是在 index.html 這檔案裏。當我們切換網頁時,其實是在 index.html 此檔案裏切換不同元件。

假設我由首頁,跳到 about 頁,再跳到 products 頁。每次跳轉都不用重刷頁面,而是切換元件即可。由始至終我都是在 index.html 此檔案裏。

比起一般傳統網頁需時重新刷新和載入頁面,感覺更為順暢和快速,體驗就如使用 App 一樣順暢,也因此我們會稱為 Single Page "Application"。

使用 AJAX 非同步遠端取資料的方式,更新部分畫面

SPA 依賴 AJAX 技術來實現局部更新畫面。

以最廣為人知的 Gmail 為例,打開 Gmail 看看,例如由收件匣頁面跳到草稿時,網頁 URL 尾部由 #inbox 轉至 #drafts,跳轉時並沒有刷新頁面。如果再仔細一點看,會發現在跳轉時,只有內容會更新,最頂部的 Navbar ,以及左邊的選單都沒有太大變化。所以,其實 Gmail 主要只需信件內容,其餘部分不需要重新載入。

因此,以上面由收件匣頁面跳到草稿的情況為例,我們只需要透過 AJAX 向後端伺服器發出請求來取得資料,即是打 API 取得此 Gmail 用戶的草稿資料。在收到 response 後,把資料掉回去前端,再利用 JavaScript,只針對右邊的內容做重新渲染,把從 response 抓回來的資料渲染上去。

在客戶端把 JavaScript 的內容渲染出來

SPA 另一個特點是在客戶端讀取 JavaScript 來渲染畫面內容,而非等後端把整個網頁內容都渲染好並掉回前端。

當用戶載入網頁時,這時候不用等後端把整個網頁內容回傳並顯示,瀏覽器只需等待伺服器回傳 HTML、CSS 和 JavaScript 這三種檔案。接著瀏覽器會把打包在 JavaScript 裏的資料內容渲染成畫面。

以 Vue CLI 所開發的網站為例,使用 npm run build 來產生 dist 資料夾打包檔案,再用 live server 插件來預覽 dist 裏的 index.html。當你用 page source 來看網頁的原始碼時,會發現此頁面並沒有資料內容,除了只有基本的 HTML,就只有一堆 CSS 和 JavaScript 檔案:

但如果是用檢查元素的方式去看,就會發現內容,例如是 nav 的內容:

以上差別明顯可見,網頁的內容都是由瀏覽器透過讀取 JavaScript 來渲染。

補充一點,Vue、React、Angular 三大前端框架都是 SPA 框架(Single Page Application)。SPA 是一個開發模式,正如常見後端會採用 MVC 模式一樣,所以即使不使用 Vue、React 這些框架,用原生 JavaScript 或 jQuery 等都可以完成一個 SPA 的網頁。

什麼是 SSR?

SSR(server side render)就是 SPA 還沒出現時所採用的傳統做法。重點如下:

  • 伺服器回傳完整 HTML 檔案給前端作顯示
  • 每次跳轉到新頁面,瀏覽器都需要刷新頁面

伺服器回傳完整 HTML 檔案給前端作顯示

常見做法透過 MVC(Model、View、Controller)的架構,在後端完成:

  • 接收前端請求
  • 按請求操控資料庫來取得所需資料
  • 把取回來的資料,塞進模版裏,產生完整 HTML 檔案,把它傳回前端

前端的職責相對少,只需直接把收到的 HTML 檔案顯示出來就完成。

每次跳轉到新頁面,瀏覽器都需要刷新頁面

每當用戶訪問一個網頁,後端就要回傳一次新的 HTML 檔案給前端。因此每次跳轉網頁時都會重新刷新頁面,導致使用流暢度明顯比 SPA 差。

SPA 與 SSR 的優劣

雖然聽來 SPA 比較優勝,但是兩者都有限制。

SPA

SPA 優點:

  • 使用者體驗更順暢,跳轉頁面時不用等重新刷新頁面。
  • 明確的前後端分離,後端只需專注資料回傳和資料庫操作。前端只需專注畫面。

SPA 限制:

  • 不利於搜尋引擎爬蟲運作,不利SEO。因為內容是透過瀏覽器自己再渲染出來,在原始碼只會見到此網站載入了一些 JavaScript 檔案,因此在爬蟲爬內容時會有影響。

SSR

SSR 優點:

  • 有利於 SEO

SSR 限制:

  • 使用者體驗相對差。每次跳轉頁面都要重新刷新畫面
  • 等待時間有機會較長,只要有一個請求卡住,後端都要等它完成再一次過把完整的 HTML 檔案回傳到前端。但 SPA 因為是依靠非同步 AJAX 技術來取資料,因此可以先回傳一部分已成功抓取的資料,不至於完全沒畫面。
  • 沒有前後端分離。後端要一併處理畫面、前端請求和資料庫。
  • 如果網站流量較大,對伺服器的負擔會比較重。因為每個請求都要求後端回傳一個完整的 HTML 檔案。相比 SPA 依靠 AJAX 來取資料,負擔明顯更大。

二合一的解決方案:前端 SSR 框架

為了解決 SPA 的 SEO 問題,最常見方法之一是使用前端的 SSR 框架。在 Vue 的生態圈就是使用 Nuxt.js 框架。核心概念就是在首次載入畫面時用 SSR 模式,跑完一次 SSR 後,往後所有請求都是 SPA 進行,運作流程如下:

  1. 瀏覽器發出請求,向 Nuxt.js 所包含的 Node.js 伺服器請求取得資料
  2. 如果有需要打 API 取資料,Node.js 伺服器會在這候打 API 取資料
  3. 把取得的資料產生一個完整 HTML 檔案,再回傳到前端
  4. 完成一次以上步驟後,之後就會轉換為 SPA 模式,所有請求都會用 AJAX 來處理

這二合一的解決方法就能同時兼顧 SEO 和使用者體驗。較明顯的代價是:

  • 前端要再顧及一個後端伺服器,以致有兩個後端的情況,這也影響到前端的部署方式。
  • Nuxt.js 不是由 Vue 官方開發,因此會出現像是 Vue 升級成為 Vue 3,但 Nuxt 還未能支援 Vue 3 的尷尬情況。
  • 前端的工作變得更複雜,要考慮某些內容和套件,到底是適合在 SSR 還是 SPA 處理和使用。

雖說 Nuxt 是 SPA + SSR 框架,但在 Nuxt 裏,只不過它預設是 SPA + SSR 模式,如果你只想要 SPA,也可以在 Nuxt 的 nuxt.config.js 檔案裏做設定。

預設模式是 universal,即是 SSR 加 SPA。以下示範用 Nuxt 建立一個專案,並在 Nuxt 載入第一頁面時檢查原始碼,會發現有網頁內容。有找到在網頁中 Welcome to your Nuxt Application 這一句:

把設定轉為 SPA 模式,就沒有網頁內容,只是載入 JavaScript 檔案。沒找到在網頁中 Welcome to your Nuxt Application 這一句:

原因就如以上提過,因為 SPA 是以讀取 JS 檔案來渲染內容,並不像 SSR ,直接在 HTML 裏就找到內容。

總結

總結一下重點:

  • Vue 是 SPA 框架。
  • SSR 是較傳統做法,後端把整個 HTML 回傳到前端顯示。
  • SPA 依賴 AJAX 技術,後端只需回傳資料到瀏覽器,前端會負責做渲染。
  • Nuxt 是 SSR+SPA 的框架,為了解決 Vue 的 SEO 問題而出現。

參考資料

Server-side rendering with Vue and Nuxt.js
Server side render (SSR) 是什麼嗎? 為何要用 SSR ? 跟 SPA 和 SEO 又有什麼關聯?
前後端分離與 SPA
Vue 服务端渲染原理及入门


上一篇
不只懂 Vue 語法:Vue 的 MVVM、漸進式框架、宣告式渲染是指什麼?
下一篇
不只懂 Vue 語法:請說明 Vue CLI 的目錄架構?
系列文
不只懂 Vue 語法:Vue.js 觀念篇31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
tsuifei
iT邦新手 4 級 ‧ 2021-10-20 03:37:24

解釋的好清楚!尤其是兩者並用的部份。謝謝妳~

我要留言

立即登入留言