Next.js 渲染攻略:SSR、CSR、ISR 怎麼選?
1. SSR(Server-Side Rendering,伺服器端渲染)
什麼是 SSR?
SSR 是在伺服器端生成完整的 HTML 內容,然後將其傳送給瀏覽器。每次使用者請求頁面時,伺服器都會動態生成最新的 HTML。
特點:
-
SEO 友好:因為伺服器直接傳送完整的 HTML,搜尋引擎可以輕易爬取內容。
-
首次載入速度快:使用者會立即看到完整的頁面內容,不需等待 JavaScript 在瀏覽器執行。
-
伺服器負擔較重:每次請求都需要伺服器重新生成 HTML,對於高流量網站可能需要更多伺服器資源。
-
互動性稍慢:頁面雖然快速顯示,但需要等待伺服器回應,且後續的互動可能需要額外的客戶端 JavaScript。
什麼時候使用 SSR?
-
頁面內容高度依賴動態數據(例如即時更新的新聞頁面)。
-
需要優化 SEO 的頁面。
-
希望使用者快速看到完整內容。
Next.js 中的 SSR 實現
在 Next.js 中,SSR 使用 getServerSideProps 函數來實現。這個函數在每次請求時於伺服器端執行,獲取數據並傳遞給頁面元件。
程式碼範例
假設你正在建一個顯示即時用戶資料的頁面:
// pages/user/[id].js
import React from 'react';
export default function UserProfile({ user }) {
return (
<div>
<h1>用戶資料</h1>
<p>姓名:{user.name}</p>
<p>電子郵件:{user.email}</p>
</div>
);
}
export async function getServerSideProps(context) {
const { id } = context.params; // 從 URL 獲取動態參數
// 模擬從 API 獲取用戶資料
const response = await fetch(`https://api.example.com/users/${id}`);
const user = await response.json();
return {
props: {
user, // 將數據傳遞給元件
},
};
}
步驟解析:
-
當使用者訪問 /user/123 時,Next.js 會在伺服器端執行 getServerSideProps。
-
getServerSideProps 從 API 獲取用戶資料,並將其作為 props 傳遞給 UserProfile 元件。
-
伺服器生成完整的 HTML 並傳送給瀏覽器。
-
使用者立即看到渲染好的頁面。
注意事項:
-
getServerSideProps 只在伺服器端執行,不能在瀏覽器端運行。
-
如果 API 回應慢,頁面載入時間會變長,因為伺服器必須等待數據。
2. CSR(Client-Side Rendering,客戶端渲染)
什麼是 CSR?
CSR 是指頁面的 HTML 由瀏覽器中的 JavaScript 動態生成。伺服器僅提供一個空的 HTML 框架,JavaScript 在客戶端執行後才渲染出內容。
特點:
-
首次載入慢:使用者需要等待 JavaScript 下載、解析並執行,才能看到頁面內容。
-
SEO 不友好:因為初始 HTML 幾乎是空的,搜尋引擎可能無法正確爬取內容。
-
伺服器負擔輕:伺服器只需傳送靜態檔案(HTML、CSS、JavaScript),無需動態生成內容。
-
互動性強:適合需要高度互動的應用,例如單頁應用(SPA)。
什麼時候使用 CSR?
-
頁面內容高度依賴用戶互動(例如即時聊天應用)。
-
不需要 SEO 或 SEO 不是首要考量。
-
希望減少伺服器負擔。
Next.js 中的 CSR 實現
在 Next.js 中,CSR 通常透過 React 的 useEffect 和 useState 來實現數據獲取和渲染。Next.js 預設會將頁面作為靜態頁面處理,但你可以在客戶端動態獲取數據。
程式碼範例
假設你正在建一個顯示用戶清單的頁面:
// pages/users.js
import React, { useState, useEffect } from 'react';
export default function UsersList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUsers() {
setLoading(true);
// 模擬從 API 獲取用戶清單
const response = await fetch('https://api.example.com/users');
const data = await response.json();
setUsers(data);
setLoading(false);
}
fetchUsers();
}, []);
if (loading) {
return <div>載入中...</div>;
}
return (
<div>
<h1>用戶清單</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
步驟解析:
-
頁面載入時,Next.js 傳送一個空的 HTML 框架和 JavaScript 檔案。
-
瀏覽器執行 useEffect,向 API 發送請求並獲取用戶清單。
-
數據獲取完成後,React 更新狀態並重新渲染頁面,顯示用戶清單。
-
在數據載入期間,顯示「載入中...」以提升用戶體驗。
注意事項:
-
如果 JavaScript 檔案很大或網路慢,使用者可能會看到空白頁面或載入指示器。
-
搜尋引擎可能無法正確索引動態生成的內容。
3. ISR(Incremental Static Regeneration,增量靜態再生)
什麼是 ISR?
ISR 是 Next.js 提供的一種混合渲染方式,結合了靜態生成(SSG)和動態更新的優點。頁面在建置時生成靜態 HTML,但可以設定一個週期(例如每 60 秒),讓 Next.js 在背景重新生成頁面,更新內容。
特點:
-
SEO 友好:生成的是靜態 HTML,搜尋引擎可以輕易爬取。
-
首次載入快:靜態頁面直接從 CDN 提供,無需伺服器即時運算。
-
動態更新:透過設定 revalidate 時間,頁面可以定期更新,無需重新建置整個網站。
-
靈活性高:適合需要定期更新的內容,例如部落格文章或產品頁面。
什麼時候使用 ISR?
-
頁面內容需要定期更新,但不需要即時動態數據。
-
希望兼顧 SEO 和快速載入體驗。
-
適合流量較高的網站,因為靜態頁面可由 CDN 提供,減少伺服器負擔。
Next.js 中的 ISR 實現
在 Next.js 中,ISR 使用 getStaticProps 並搭配 revalidate 選項來實現。getStaticProps 在建置時執行,生成靜態頁面,而 revalidate 指定頁面重新生成的週期。
程式碼範例
假設你正在建一個顯示最新部落格文章的頁面:
// pages/blog.js
import React from 'react';
export default function Blog({ posts }) {
return (
<div>
<h1>最新文章</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export async function getStaticProps() {
// 模擬從 API 獲取文章資料
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
return {
props: {
posts, // 將文章資料傳遞給元件
},
revalidate: 60, // 每 60 秒重新生成頁面
};
}
步驟解析:
-
在建置時,Next.js 執行 getStaticProps,從 API 獲取文章資料並生成靜態 HTML。
-
靜態頁面儲存在伺服器或 CDN,供使用者快速訪問。
-
當使用者訪問頁面時,Next.js 提供靜態 HTML,無需即時運算。
-
每 60 秒(由 revalidate: 60 指定),Next.js 在背景檢查是否有新數據,若有則重新生成頁面。
-
如果 API 數據更新,使用者會在下一次請求時看到最新的靜態頁面。
注意事項:
-
revalidate 的時間單位是秒,設定太短可能增加伺服器負擔,太長則可能導致內容不夠即時。
-
如果 API 請求失敗,Next.js 會繼續提供舊的靜態頁面,確保網站可用性。
SSR、CSR、ISR 的比較表
特性 | SSR(伺服器端渲染) | CSR(客戶端渲染) | ISR(增量靜態再生) |
---|---|---|---|
渲染地點 | 伺服器端 | 客戶端(瀏覽器) | 建置時 + 伺服器端(背景更新) |
首次載入速度 | 快(伺服器生成 HTML) | 慢(需下載 JS 並執行) | 非常快(靜態 HTML 從 CDN 提供) |
SEO 友好性 | 高 | 低 | 高 |
伺服器負擔 | 高(每次請求都生成) | 低(僅傳送靜態檔案) | 低(靜態頁面 + 背景更新) |
數據即時性 | 高(每次請求都更新) | 高(客戶端即時請求) | 中(取決於 revalidate 時間) |
使用場景 | 動態內容、SEO 重要 | 高度互動的應用 | 定期更新的內容、SEO 重要 |
如何選擇?
-
如果需要 SEO 和快速首次載入:
-
首選 ISR,因為它兼顧了靜態生成的性能和動態更新的靈活性。
-
如果內容必須即時更新,選擇 SSR。
-
-
如果頁面高度互動且 SEO 不是重點:
- 使用 CSR,例如儀表板或即時應用。
-
如果網站流量高:
- ISR 或靜態生成(SSG)更適合,因為它們利用 CDN 減少伺服器負擔。