# Next.js 概述 <center><img src="https://images.prismic.io/techloset/Z1_3cpbqstJ98iN__a-complete-guide-to-next-js-a-react-js-framework.webp?auto=format%2Ccompress&fit=max&w=3840" /></center> 前言 --- 「React 是一個非常出色的 **前端框架 (JavaScript Framework)**,它讓我們能用『元件 (Components)』來打造互動式的『客戶端 (Client-Side)』介面。 但是,當我們用 React 打造一個完整的『應用程式 (Application)』時,尤其是在生產環境 (Production),我們會遇到幾個核心挑戰: - **SEO (搜尋引擎優化) 問題:** 傳統 React (CSR) 交付給瀏覽器的是一個幾乎空白的 HTML 和一包 JavaScript。搜尋引擎爬蟲可能只看到空白頁面,不利於網站排名。我們後續會講解 CSR 以及 **SSR (Next.js 的精隨)** 是甚麼。 - **首屏載入效能 (Initial Load Performance):** 使用者需要先下載完 JavaScript 檔案,然後在瀏覽器上執行 React,才能看到畫面。在網路較慢或設備效能較差時,使用者會面對一段時間的白畫面。 - **架構的功能缺乏性:** 因為 React 這個框架本身只管 UI,所以我們需要自己決定如何處理:**路由 (Routing)**、**資料請求 (Data Fetching)**、**程式碼分片 (Code Splitting)**、**圖片優化**...等等。 **而 Next.js 就是為了解決這些問題而生的。** 但是這個框架它不是來取代 React 的,而是 React 的 **『生產環境框架 (Framework)』**。它在 React 之上,提供了一套完整、高效能的架構和『預設的最佳實踐 (Defaults and Conventions)』,讓我們能專注在業務邏輯,同時免費獲得 SSR、SSG 等強大功能。」 核心概念 (一) - 渲染模式 (Rendering Strategies) - 解決 SEO 與效能 --- ### 四大渲染模式 - **CSR (Client-Side Rendering):** 傳統 React 渲染模式。Next.js 依然支援。 - **客戶端渲染的比喻:** - IKEA 倉庫(伺服器)寄給你一個「包裹」。 - 這個包裹就是**空白的 HTML** 和**一大包 JavaScript(零件和說明書)**。 - 包裹本身不是椅子。你(客戶端瀏覽器)必須在你的客廳裡,自己打開包裹,看著說明書(執行 JS),花時間把椅子「組裝」起來(渲染出畫面)。 - **簡單總結:** 「先拿到一堆零件,然後自己忙半天才能用。」 - **SSR (Server-Side Rendering):** **每次請求 (Request) 都在伺服器上** 產生 HTML。 - **優點:** 對 SEO 友好、使用者能更快看到畫面、適合資料頻繁變動的頁面(例如:會員中心)。 - **伺服端渲染的比喻:** - 你打電話給木工師傅(伺服器),說:「我現在要一張椅子。」 - 師傅 **「立刻」** 在他的工作室(伺服器)裡,為你量身打造這張椅子。 - 完成後,他直接把一張 **「組裝好的完整椅子」**(HTML)運到你家。你一拿到就能立刻使用。 - **簡單總結:** 「向師傅下訂單 **(向伺服器請求)**,然後拿到客製化的成品 **(HTML)**。」每次下單,師傅都會重做一次。 - **SSG (Static Site Generation):** **在建構 (Build Time) 時就** 產生所有 HTML 頁面。 - **優點:** 速度最快(可被 CDN 緩存)、最安全、對 SEO 最好。適合內容不常變動的頁面(例如:部落格文章、行銷頁面)。 - **ISR (Incremental Static Regeneration):** SSG 的進化版。在背景「增量」重新產生靜態頁面,讓靜態網站也能擁有動態更新的資料。 ### CSR (for React) v.s SSR (for Next.js) - Diagram <center><img src="https://hackmd.io/_uploads/Hk4l_AlJWg.png" /></center> 核心概念 (二) - 路由系統 (Routing System) - 解決架構 --- 在過去,頁面的路由上,無論是 Pages Router 還是 React Router,我們的思考都是『一個**檔案**對應一個**頁面**』。 > **Pages Router 範例:** > > - `pages/about.js` → 變成 `/about` 路由 > > - `pages/dashboard.js` → 變成 `/dashboard` 路由 但在 App Router 中,這個思想改變了。 **核心轉變:『一個資料夾代表一個路由 (Route Segment),裡面的 `page.js` 才是該路由的 UI。』** > **App Router 範例:** > > - `app/about/page.js` → 變成 `/about` 路由 > > - `app/dashboard/page.js` → 變成 `/dashboard` 路由 為什麼要這麼麻煩,多一層資料夾?因為這帶來了 App Router 最強大的功能... **巢狀佈局 (Nested Layout)** ### 巢狀佈局 (Nested Layout) <center><img src="https://upload.wikimedia.org/wikipedia/commons/4/4a/%D0%9C%D0%B0%D1%82%D1%80%D1%91%D1%88%D0%BA%D0%B0-Russian_leaders_%E3%83%9E%E3%83%88%E3%83%AA%E3%83%A7%E3%83%BC%E3%82%B7%E3%82%AB_Shimada22.jpg" /></center> 巢狀佈局就好像是「俄羅斯娃娃」一樣,讓網頁變成一層一層嵌套的形式。 **請記住兩個最重要的特殊檔案:** 1. **`layout.js`:** 這就是 **『娃娃的殼』**。它是一個共享的 UI,負責包裹住在它內部的所有東西。 2. **`page.js`:** 這就是 **『娃娃的臉』** 。它是這個路由實際要顯示的、獨一無二的內容。 ``` app/ ├── layout.js # 娃娃 1 (最大隻的娃娃) 的殼 │ # (裡面放 <html>, <body>, Navbar, Footer) │ ├── page.js # 娃娃 1 的臉 (首頁 /) │ └── dashboard/ │ ├── layout.js # 娃娃 2 (中間的娃娃) 的殼 │ # (裡面放 Sidebar) │ ├── page.js # 娃娃 2 的臉 (儀表板首頁 /dashboard) │ └── settings/ │ ├── layout.js # 娃娃 3 (最小的娃娃) 的殼 │ └── page.js # 娃娃 3 的臉 (設定頁 /dashboard/settings) ``` 現在,我們來看當使用者瀏覽不同頁面時,Next.js 是怎麼『組裝』這些娃娃的: * **當使用者去看首頁 (`/`):** * Next.js 會拿 `app/page.js` (首頁的臉) * ...然後把它放進 `app/layout.js` (最大的殼) 裡。 * **結果:** `[Navbar + [首頁內容] + Footer]` * **當使用者去看儀表板首頁 (`/dashboard`):** * Next.js 會拿 `app/dashboard/page.js` (儀表板的臉) * ...把它放進 `app/dashboard/layout.js` (帶有 Sidebar 的殼) 裡。 * ...然後再把**整組**放進 `app/layout.js` (最大的殼) 裡。 * **結果:** `[Navbar + [Sidebar + [儀表板內容]] + Footer]` * **當使用者去看儀表板中的設定頁 (`/dashboard/settings`):** * Next.js 會拿 `app/dashboard/settings/page.js` (設定頁的臉) * ...把它放進 `app/dashboard/layout.js` (Sidebar 的殼) 裡。**(注意:這裡沒有 `settings/layout.js`,所以它會自動找上一層的 `layout` 來用!)** * ...最後再把**整組**放進 `app/layout.js` (最大的殼)。 * **結果:** `[Navbar + [Sidebar + [設定頁內容]] + Footer]`」 ### 示意圖 <center><img src="https://hackmd.io/_uploads/HkVnDGc1Zl.png" /></center> 核心概念 (三) - API 路由 - 整合後端接口 --- Next.js 允許你直接在專案中建立後端 API。 * **如何運作:** 放在 `pages/api/` 或 `app/api/` 資料夾下的檔案,會成為一個 API 端點 (Endpoint)。 * **優點:** 不需要額外架設一個 Node.js 伺服器。非常適合處理簡單的後端邏輯,例如:表單提交、連接資料庫、驗證...等。這就是所謂的 **BFF (Backend for Frontend)**。 <center><img src="https://hackmd.io/_uploads/BJlrDL7JWx.png" /></center> 核心概念 (四) - React Server Components (RSC) --- * **Server Components (伺服器元件):** 預設在 **伺服器端** 執行的元件。它們**不會**被下載到客戶端,JavaScript 體積 (Bundle Size) 為 0。 * **Client Components (客戶端元件):** 傳統的 React 元件。需要互動 (如 `useState`, `onClick`) 的元件,必須加上 `"use client";` 標記。 光看以上對於這兩種 Component 的介紹可能不太懂。沒關係我們講得更清楚一些。 * **Server Components (伺服器元件):** 就像是部落格的文章。當我們進入到部落格的文章頁面時,文章、作者、留言都會被加載,這些東西跟動作都是會透過 Server 去進行資料抓取,**使用者並不需要進行動作**,並且合成一個 HTML 檔案之後丟給客戶端,這些只需要靠 Server 就可以完成的物件,我們稱為 RSC。 * **Client Components (客戶端元件):** 就像是部落格的留言區。你可以點讚、留言,這些動作不可能是由伺服器去幫你執行的,**而這些需要互動屬性的物件**,我們稱為 RCC 。 核心概念 (五) - 內建優化 (Built-in Optimizations) --- Next.js 幫我們處理了很多麻煩的效能優化。 * **`<Image>` 元件:** 自動處理圖片優化(壓縮、轉檔 WebP)、響應式圖片、延遲載入 (Lazy Loading)。 * **`<Link>` 元件:** 簡化前端路由,並自動在背景預先載入 (Prefetch) 連結頁面的資源,讓換頁體感極快。 * **字體優化 (`next/font`):** 自動處理 Google Fonts 或本地字體,避免「字體閃爍 (FOUT)」和「版面位移 (Layout Shift)」。 --- 文件參考:https://nextjs.org/docs