歷史
最早的網頁內容是在 server 中,將 html 模板(字串)與變數組合後回傳給瀏覽器顯示像是 PHP。
import { createServer } from "http";
createServer(async (req, res) => {
const content = "Hello World";
res.setHeader("Content-Type", "text/html");
res.end(`<html>
<head>
<title>blog</title>
</head>
<body>${content}</body>
</html>`);
}).listen(3000);
但是直接操作字串做開發不是很理想,內容一但變得複雜將會很難維護。理想上是可以將內容拆分成一塊一塊的積木,最後可以互相的嵌入與移除。
JSX
JSX是 React.createElement 的語法糖,建立 React 元件時不用每次都寫 createElement。
const element = <h1 className="greeting">Hello!</h1>;
// 等同於;
const element = React.createElement("h1", { className: "greeting" }, "Hello, World!");
CSR/SSR
在 SPA(Single-Page App)上,當使用者發送 request 到 server,server 會回傳只包含<div id='root'/>
的 html 與 js 檔案。瀏覽器執行 js 檔案將整個 JSX 物件掛在<div id='root'/>
後頁面才會顯示。
SPA 缺點:
- 對 SEO 不友善,爬蟲只能爬到空的
<div>
無法得知裡面內容 - 瀏覽器在執行 js 需要時間,會造成頁面空白一陣子才顯示內容。
- API 呼叫全都在 client 端會造成 waterfall
SSR(Server-Side Rendering):
提早在 server 上將 JSX 轉換成 HTML 字串。瀏覽器在回應時會有預先的內容能夠顯示,而不是只有一個空白的<div>
元素。
RSC(React Server Component)
RSC 主要想法是讓元件能夠直接存取資料庫、檔案,讓一些能在 server 處理的事留在 server 處理,例如 API call、第三方套件。在 server 處理的 API 與第三方套件的 bundle 也不會傳至 client,可以減少 bundle size。
RSC 在產生 React Tree 時,如果遇到 client component 時,會使用 placeholder 表示,placeholder 中會紀錄載入 client 元件位置,之後再透過瀏覽器將 client 元件載入。
placeholder範例
{
$$typeof: Symbol(react.element)
type: {
$$typeof: Symbol(react.module.reference),
name: 'default'
filename: './src/component.client.js'
}
}
- React Tree 的 root 一定是 server component。
- client component 不能 import server component,因為 server component 不能在瀏覽器上執行。
- RSC 的回傳格式透過
renderToReadableSream(<App />)
回傳 streaming 資料,像是一塊一塊的積木,這些 streaming 資料瀏覽器是看不懂的,需要再轉換成 html 讓瀏覽器顯示(在 server 轉就是 SSR,在 client 轉就是 CSR)。RSC範例1:"$Sreact.suspense" 0:[["$","h1",null,{"children":"Hello world"}],["$","$1",null,{"fallback":"Loading...","children":"$L2"}]] 2: ....
- 原本是用檔名來區分是 server 元件還是 client 元件,例如
index.server.tsx
或是index.client.tsx
。後來改成在檔案的最前面加上'use client'
、'use server'
來區分。
依據React server components from scratch! - YouTube這個實作畫的流程圖
- 使用者訪問
/
路由 - Server 回傳 HTML、JS
- 這裡的範例是 Client Side Rendering(CSR)
- 拿到 JS 後會再向 Server 發送
/rsc
請求,取得 RSC。再透過瀏覽器 render RSC