cover

概念概覽

flowchart LR
    MPA["傳統 MPA<br/>全頁刷新<br/>2000s"] --> AJAX["AJAX<br/>局部更新<br/>2005+"]
    AJAX --> SPA["SPA<br/>單頁應用<br/>2013+"]
    SPA --> SSR["SSR / SSG<br/>同構渲染<br/>2016+"]
    SSR --> ISR["ISR / Streaming<br/>混合渲染<br/>2022+"]

    style MPA fill:#fdd,stroke:#333
    style AJAX fill:#fed,stroke:#333
    style SPA fill:#dfd,stroke:#333
    style SSR fill:#ddf,stroke:#333
    style ISR fill:#fdf,stroke:#333

架構演進歷程

傳統 MPA → AJAX → SPA → SSR/SSG → ISR/Streaming
  │         │       │       │           │
  │         │       │       │           └─ 2022+ 混合渲染
  │         │       │       └─ 2016+ 同構渲染
  │         │       └─ 2013+ 單頁應用
  │         └─ 2005+ 局部更新
  └─ 2000s 全頁刷新

1. 傳統 MPA(Multi-Page Application)

運作方式:每次請求都由伺服器產生完整 HTML 頁面

瀏覽器                        伺服器
   │                            │
   │ ─── GET /page1 ──────────→ │
   │ ←── HTML (完整頁面) ─────── │
   │                            │
   │ ─── GET /page2 ──────────→ │  (整頁刷新)
   │ ←── HTML (完整頁面) ─────── │

技術:PHP、Ruby on Rails、Django、Laravel

優點

  • SEO 友好
  • 首屏載入快
  • 實作簡單

缺點

  • 每次換頁都要重新載入
  • 使用者體驗不佳
  • 伺服器負擔重

2. AJAX 局部更新

運作方式:透過 JavaScript 局部更新頁面內容

// 使用 AJAX 取得資料並更新部分頁面
fetch('/api/posts')
  .then(res => res.json())
  .then(posts => {
    document.getElementById('posts').innerHTML =
      posts.map(p => `<div>${p.title}</div>`).join('');
  });

改進:不需要整頁刷新,提升使用者體驗

3. SPA(Single-Page Application)

運作方式:首次載入完整應用,之後透過 API 取得資料

首次載入
瀏覽器                        伺服器
   │                            │
   │ ─── GET / ───────────────→ │
   │ ←── HTML + JS Bundle ───── │
   │                            │

後續導航(不重新載入頁面)
   │ ─── GET /api/users ──────→ │
   │ ←── JSON ────────────────── │
   │                            │
   │  (前端 Router 處理路由)     │

技術:React、Vue、Angular

優點

  • 流暢的使用者體驗
  • 前後端完全分離
  • 可離線運作(PWA)

缺點

  • 首屏載入慢(需下載大量 JS)
  • SEO 困難
  • 需要 JavaScript 才能運作

4. SSR(Server-Side Rendering)

運作方式:首次由伺服器渲染 HTML,之後轉為 SPA

首次載入(SSR)
瀏覽器                        伺服器
   │                            │
   │ ─── GET /posts ──────────→ │
   │                    ┌───────────────┐
   │                    │ React 渲染成 │
   │                    │ HTML 字串    │
   │                    └───────────────┘
   │ ←── HTML + JS ─────────── │
   │                            │
   │  (Hydration: HTML 變成可互動)

後續導航(CSR)
   │ ─── GET /api/posts/2 ────→ │
   │ ←── JSON ─────────────────  │

技術:Next.js、Nuxt.js、Remix

優點

  • SEO 友好
  • 首屏載入快
  • 可互動性佳

缺點

  • 伺服器負擔較重
  • TTFB(Time To First Byte)較慢
  • 開發複雜度增加

5. SSG(Static Site Generation)

運作方式:建置時預先產生所有靜態頁面

建置階段
┌─────────────────────────────────────┐
│  npm run build                       │
│                                      │
│  /posts/1.md  →  /posts/1.html      │
│  /posts/2.md  →  /posts/2.html      │
│  /posts/3.md  →  /posts/3.html      │
└─────────────────────────────────────┘
        ↓
    上傳到 CDN

請求階段
瀏覽器 ───→ CDN ───→ 回傳靜態 HTML(極快)

技術:Gatsby、Next.js(getStaticProps)、Hugo、Quartz

優點

  • 極快的載入速度
  • 可以放 CDN
  • 安全(沒有伺服器)

缺點

  • 不適合頻繁更新的內容
  • 建置時間長(頁面多時)

6. ISR(Incremental Static Regeneration)

運作方式:靜態頁面 + 背景更新

// Next.js ISR
export async function getStaticProps() {
  const posts = await fetchPosts();
  return {
    props: { posts },
    revalidate: 60, // 60 秒後重新產生
  };
}

流程

  1. 首次請求:返回靜態頁面
  2. 60 秒後:背景重新產生頁面
  3. 下次請求:返回新頁面

架構選擇指南

架構適用場景代表框架
MPA傳統網站、後台系統Laravel, Rails
SPAWeb App、DashboardReact, Vue
SSR需 SEO + 互動的網站Next.js, Nuxt
SSG部落格、文件網站Gatsby, Hugo
ISR電商、新聞網站Next.js

實務建議

需要 SEO?
  ├─ 是 → 內容常更新?
  │        ├─ 是 → SSR 或 ISR
  │        └─ 否 → SSG
  │
  └─ 否 → 複雜互動?
           ├─ 是 → SPA
           └─ 否 → MPA 或 SSG

延伸閱讀

Rendering on the Web 前後端分離 - 序章 MVC 架構