[Web] Next.js (React 全端框架) 開發指南

Intro

Next.js 是一個開源的 React 全端框架,後端基於 Node.js。它支援多種渲染方式 (Rendering),包括伺服器端渲染 (SSR)、靜態站點生成 (SSG) 以及用於客戶端渲染 (CSR) 的 React 原生渲染模式。


安裝 Next.js


路由器選擇 - App / Page Router

從 version 13 (2022) 開始,Next.js 引入新的 App Router,與舊版 Page Router 同時並存。

  • 使用方式:
    • App Router 會解析 /app 資料夾內的路由。
    • Page Router 則繼續解析 /pages 資料夾內的路由。
  • 判定方式:
    • 兩者會同時執行,分別解析其指定的資料夾。
    • 如果兩者路徑發生衝突,Next.js 會直接回報錯誤,無法同時存在相同的路由。
  • 資料夾結構差異:
    • App Router:
      基於文件夾層結構 (File-based Routing) 設計,每個路徑由資料夾內的 page.js (或 .tsx) 文件定義。(底線 _ 路徑對應需以 %5F 命名資料夾)
      支援Server Components,可透過 loading.js、error.js 等文件定義狀態處理。
    • Page Router:
      傳統的文件為基礎 (File-based Routing) 設計,每個路由由一個 .js (或 .tsx) 文件表示。主要用於Client Components,並透過 getStaticProps、getServerSideProps 等函數實現資料獲取。
特性 App Router (新) Page Router (舊)
資料夾結構 /app 資料夾 /pages 資料夾
元件模型 預設使用 React Server Components (RSC) 僅支援 React Client Components
路由方式 文件式路由 (File-based Routing) 同樣為 文件式路由
Layout 支援 內建 Layout, 可跨路由共享 需要手動在每頁引入 Layout
渲染模式 支援 SSR、SSG、ISR、CSR 支援 SSR、SSG、ISR、CSR
動態路由 支援動態與分段路由 (Segment Routing) 只支援傳統動態路由
Loading 狀態 內建 loading.js,自動管理狀態 需手動在元件內處理
API 路由 使用 /app/api 使用 /pages/api
SEO 處理 使用 metadata 檔案設定 需使用 Head 元件手動設定
靜態資源 (Assets) 可從 /public 資料夾訪問 相同使用 /public

Deploying

Static Export

Next.js 官網 - Static Exports 提供了一個根目錄 host 的通用場景,並對 /blog/ 子目錄設定 rewrite 模擬 Clean URL 效果

優化 - Clean URL

若要達到全目錄 Clean URL:

  • nextConfig trailingSlash: 主要透過每頁轉成資料夾形式達到 Clean URL,out 產出結構會類似 App Router 結構
    (e.g. app/about/page.tsx => out/about/index.html)
  • 基於 trailingSlash 在網址隱藏各目錄下的 index.html & index.txt: 可以透過 Nginx 設定比對轉導:
    location / {
    # Redirect requests ending with index.html or index.txt under the directory
    if ($request_uri ~ ^(/.*)index\.(html|txt)$) {
        return 302 $1;
    }
    try_files $uri $uri.html $uri/ =404;
    }

在子目錄建置網站

若要在子目錄(sub-directory)下建置靜態網站,就會需要使用 nextConfig basePath 設定:

const nextConfig = {
    output: 'export', // Exports the app as static HTML files
    trailingSlash: true, // Adds a trailing slash to the end of each route (e.g., /about/)
    basePath: '/nextjs/out', // Your desired path prefix
}

然而如 Next.js 官網 所述,Image 不支援自動載入 basePath。較好的解決方式是從 next.config.js import basePath 來定義 Image src:

import { basePath } from '../next.config';

<Image src={${basePath}/next.svg}/>

Nginx location 設定 (子目錄路徑得 hardcore 重複設定):

 # Apply the rewrite for /nextjs/out
location /nextjs/out {

    # Redirect requests ending with index.html or index.txt to the directory
    if ($request_uri ~ ^/nextjs/out(/.*)index\.(html|txt)$) {
        return 302 /nextjs/out$1;
    }

    # Try to serve files; if not found, return 404
    try_files $uri $uri/ =404;

    # Define the custom 404 error page
    error_page 404 /nextjs/out/404.html;
}

References

Leave a Reply

Your email address will not be published. Required fields are marked *