CAFECA-IO / KnowledgeManagement

Creating, Sharing, Using and Managing the knowledge and information of CAFECA
https://mermer.com.tw/knowledge-management
MIT License
0 stars 1 forks source link

[KM] App Router vs Pages Router in Next.js (撰寫 part 8) #252

Closed godmmt closed 2 months ago

godmmt commented 2 months ago

文章位置: https://github.com/CAFECA-IO/KnowledgeManagement/blob/master/NextJs/app-router-vs-pages-router-in-next-js.md

godmmt commented 2 months ago

混用客戶端元件和伺服器元件

在 Next.js 的 App Router 中,Server Components 和 Client Components 可以混合使用。

混合使用的注意事項:

godmmt commented 2 months ago

混合使用 Server Components 和 Client Components 時,傳遞 props 是一個需要特別注意的部分,因為伺服器與客戶端的運作環境不同。

以下是 props 傳遞時的主要注意事項:

1. Server Components 可以傳遞任何類型的 props

export default async function ServerComponent() {
  const data = await fetchDataFromAPI();
  return <ClientComponent data={data} />;
}

2. Client Components 只能接收序列化後的 props

// 這樣是行不通的,因為函數無法序列化
export default function ServerComponent() {
  const myFunction = () => console.log('Hello');
  return <ClientComponent onClick={myFunction} />;
}

// 改成這樣,傳遞可序列化的資料
export default function ServerComponent() {
  const message = 'Hello';
  return <ClientComponent message={message} />;
}

3. Server Components 可以從其他 Server Components 接收 props

export default function ParentServerComponent() {
  const data = { name: "John", age: 30 };
  return <ChildServerComponent person={data} />;
}

function ChildServerComponent({ person }) {
  return <div>{person.name}</div>;
}

4. Client Components 從 Server Components 接收 props 的限制

export default function ServerComponent() {
  const date = new Date().toISOString(); // 確保可以序列化
  return <ClientComponent dateString={date} />;
}

("use client");
export function ClientComponent({ dateString }) {
  const date = new Date(dateString);
  return <p>{date.toDateString()}</p>;
}

5. 避免傳遞大型物件或敏感資料

godmmt commented 2 months ago

在 Next.js App Router 中,Client Components 和 Server Components 各自有不同的用途和限制。具體來說,Client Components 可以使用許多 React 客戶端的功能,但這些功能無法在 Server Components 中使用。

以下是一些只能在 Client Components 使用,而不能在 Server Components 使用的功能:

1. React Hooks

2. 事件處理 (Event Handlers)

3. 瀏覽器 API

4. 動態導入和互動行為

5. CSS-in-JS 和客戶端樣式處理

6. React Portals

7. 互動式第三方庫

8. Cookies 和 Storage 的操作

9. 使用者互動的第三方工具

10. WebSockets 或 SSE (Server-Sent Events)

godmmt commented 2 months ago

客戶端元件不能包裹伺服器元件,這是因為伺服器元件是在伺服器端執行並生成靜態 HTML,而客戶端元件是在客戶端執行的動態 JavaScript 元件。

具體原因如下:

  1. 執行環境不同伺服器元件 是在伺服器端運行,負責處理資料並生成靜態內容,而客戶端元件在客戶端運行,負責處理互動和更新 UI。因為客戶端元件需要在瀏覽器上運行,它無法先包裹一個在伺服器端生成的靜態內容(伺服器元件)。
  2. 渲染順序: Next.js 的渲染流程是由伺服器先處理並生成伺服器元件的靜態 HTML,然後在瀏覽器上載入客戶端元件並處理互動。 伺服器元件可以包裹客戶端元件,因為伺服器會先渲染出靜態的部分,然後由客戶端補充動態部分。但反過來,若由客戶端元件包裹 伺服器元件,瀏覽器將無法在客戶端進行伺服器端的邏輯運算。

總結:

Next.js App Router 中,客戶端元件不能包裹伺服器元件,只能是伺服器元件包裹客戶端元件。這是因為渲染流程是先由伺服器處理,再由客戶端補充互動功能。

godmmt commented 2 months ago

後端工程師對於轉換架構的看法:

  1. formidable (App Router 有內建支援)
  2. API handler (可以用 http methods)
  3. middleware (像是 URL 可以改名)
godmmt commented 2 months ago

將現有專案路由架構從 Pages Router 換成 App Router 需要做的事:

  1. 需要大量改變路由資料夾的結構
  2. 原本都是客戶端元件,換成 App Router 之後會預設成伺服器元件,如果要維持原本的客戶端元件,也就是為了要繼續使用瀏覽器 API(像是監聽事件)、React hooks(像是 state、effect)的話,就要在元件的第一行加上'use client'
  3. 原本 Pages Router 的渲染方式會用到的 getStaticProps 都需要移除。
  4. 不確定第三方套件是否有影響,要確定是否都能支援
  5. 整個專案需要重新測試
godmmt commented 2 months ago

新增補充

godmmt commented 2 months ago

0905: took 6 0906: took 2

Total time: 8

done.