前言
本篇文章簡單介紹了 Server Side Rendering 並記錄了 Udemy 上的 Server Side Rendering with React and Redux 課程筆記,希望讓讀者對 SSR 有初步認識外,也讓自己對於課程內容進一步融會貫通。
為什麼需要 Server Side Rendering ?
在學習一個技術前,都要了解為什麼要學它?以及它有什麼作用?因此這裡就簡單介紹這個技術的特色、優缺點。
在做 CSR (Client Side Rendering) 時,我們必須等待 JS 檔案(最常見的就是 webpack 編譯出來的 bundle.js)傳到瀏覽器端後才開始渲染畫面,如此一來必須花費比 SSR 更多的時間去渲染畫面,若 JS 檔案更大想必花費更多時間,並且有些資料來不及載入時搜尋引擎就先進行爬蟲了,這樣就會導致不利 SEO。
而 SSR 的優點就是解決了 CSR 的兩項缺點,以下是 SSR 的運作流程:
- 使用者進入某使用 SSR 的網站
- Server 端收到 http 請求,開始載入所需資料
- Server 端產生 HTML 發送到 Client 端(瀏覽器端)
- HTML 內需要載入 JS 檔案或其他檔案(bundle.js、JSON…)
- Server 端又收到請求,處理完成後發送到 Client 端
至於如何在 Server 端做渲染,便是透過一個叫 renderToString() 的函式包著元件,渲染結束後會返回 HTML 字串。
課程內容記錄
接下來的部分就是針對課程提到的內容做一些重點式的紀錄。
ReactDOM.hydrate()
在 Server 端時傳回的 HTML 是純畫面呈現,若要為它增加事件監聽(ex: onClick)就是使用這個函式。
StaticRouter
在 server 端要使用 SSR 的話,要用 StaticRouter,因為使用 BrowserRouter 的話,會根據 address bar 的 url 去呈現畫面,但 SSR 無法看到 address bar。
那無法看到 address bar 要如何知道目前的 url?
- req 裡面有 path 屬性
- 不再使用 express.js 去辨別路由,而是透過 react router 去辨別,因此在寫 api 的部分使用可以代表全部路徑的 * (app.get(‘*’)…)
處理 SEO
課程中使用了 react-helmet 套件,功用是可以在不同的頁面中動態的變更 <head> 標籤內的資訊,以下是程式範例:
import React from 'react';
import { renderToString } from 'react-dom/server';
import express from 'express';
import App from './src/App';
const app = express();
app.get('*', (req, res) => {
const app = renderToString(<App />);
const helmet = Helmet.renderStatic();
const html = `
<!doctype html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="app">
${app}
</div>
</body>
</html>
`;
res.send(html);
});
app.listen(3000);
比較 renderToString() vs. renderToNodeStream()
renderToString() 是盡可能地快點回傳 HTML,且是一次性回傳,在效能方面雖然花費比較多 TTFB,但回傳速度較快。
renderToNodeStream() 則是一小包一小包陸續的回傳 HTML,雖然回傳全部資料會花比較多時間,但 TTFB 花的時間比較短。
TTFB (Time To First Byte)
指網路請求發出(使用者點擊某網址的那瞬間)到接收從伺服器傳回的一個字節的這段時間。
心得
此課程也有介紹到 SSR 加入 redux 會碰到的各種問題及解決辦法,做了許多的設定…理解到不用框架去做 SSR 的缺點是邏輯架構變得相當複雜,花費更多時間處理,需要寫很多的程式在 server & client 做處理,例如像這種錯誤:
發生原因就是 server 和 client 渲染的內容需一致,如附圖一個渲染 input 另一個渲染 textarea 就會出錯,而這只是處理 SSR 的一環…
之後打算來接觸 Next.js,若有心得會再補充在本文哩~
若這篇文章對你有幫助,不妨鼓鼓掌支持一下,謝謝!