CHAPTER 09 / SERVER SIDE

後端、API、
Python

前端是櫃檯,後端是廚房。客人看不到廚房但沒它出不了菜。 這章從零教你寫後端:Node.js(接前端最順)、Python(資料 / AI 必備)、API 設計、JWT 登入。

  • 能寫 Node.js / Python 後端 API
  • 會設計 RESTful API
  • 會做使用者註冊登入(JWT)
  • 會處理檔案上傳、CORS、錯誤
  • 會看別人的後端程式碼
LESSON 9.1

什麼是後端?

使用者打開 Insight,看到自己發過的問卷。問卷存哪?密碼怎麼比對?這些使用者看不到的東西就是後端。

後端做什麼

後端語言怎麼挑

語言適合
Node.js跟前端共用 JS / TS、即時應用
PythonAI / 資料、初學最易
Go高效能、雲端基建
Java/Kotlin大公司後台、銀行
PHPWordPress、舊專案

學員最該選哪一個?Node.js(前端工程師延伸)+ Python(AI 必備)。這兩個學會走遍天下。Next.js 的 API Routes 已是 Node.js,所以你某種程度已經寫過後端了。

LESSON 9.2

HTTP 與 REST API

API = Application Programming Interface = 別人的服務跟你的程式溝通的窗口

HTTP 動詞

動詞意思範例
GETGET /users
POST新增POST /users
PUT/PATCH更新PATCH /users/1
DELETE刪除DELETE /users/1

狀態碼

RESTful 設計範例

GET    /api/posts          列出文章
GET    /api/posts/42       取單篇
POST   /api/posts          新增
PATCH  /api/posts/42       更新
DELETE /api/posts/42       刪除

GET    /api/posts/42/comments   取留言
POST   /api/posts/42/comments   新增留言
LESSON 9.3

Node.js + Express

npm init -y
npm install express
npm install -D @types/express tsx typescript
// server.ts
import express from 'express';

const app = express();
app.use(express.json());

// 假資料
let posts = [
  { id: 1, title: '第一篇' }
];

app.get('/api/posts', (req, res) => {
  res.json(posts);
});

app.post('/api/posts', (req, res) => {
  const post = { id: Date.now(), ...req.body };
  posts.push(post);
  res.status(201).json(post);
});

app.delete('/api/posts/:id', (req, res) => {
  posts = posts.filter(p => p.id !== Number(req.params.id));
  res.status(204).end();
});

app.listen(3000, () => console.log('http://localhost:3000'));

Hono:現代輕量替代

// 比 Express 快、TS 友善、可跑在 Cloudflare Workers
import { Hono } from 'hono';
const app = new Hono();
app.get('/api/posts', c => c.json(posts));
export default app;
LESSON 9.4

Python:FastAPI

FastAPI 是 Python 後端首選——快、自動產 API 文件、TS 等級的型別安全。

pip install fastapi uvicorn[standard]
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List

app = FastAPI()

class Post(BaseModel):
    id: int
    title: str

posts: List[Post] = []

@app.get("/api/posts")
def list_posts():
    return posts

@app.post("/api/posts", status_code=201)
def create_post(post: Post):
    posts.append(post)
    return post

@app.delete("/api/posts/{post_id}")
def delete_post(post_id: int):
    global posts
    posts = [p for p in posts if p.id != post_id]
    return {"ok": True}
uvicorn main:app --reload
# 開瀏覽器到 http://localhost:8000/docs 看自動產生的 API 文件!

FastAPI 自動產生 Swagger / ReDoc 文件。你寫好 API 直接給前端說「看 /docs」,溝通成本砍半。

LESSON 9.5

使用者註冊 / 登入(JWT)

密碼存法(重要)

import bcrypt from 'bcrypt';

// 註冊:存 hash 而不是明碼!
const hash = await bcrypt.hash(plainPassword, 10);
await db.users.create({ email, password: hash });

// 登入:比對
const user = await db.users.findOne({ email });
const ok = await bcrypt.compare(plainPassword, user.password);
if (!ok) throw new Error('帳密錯誤');

密碼絕對不能存明碼。就算自己網站,資料庫一外洩使用者一輩子的密碼通通暴露,他們可能在別的網站用同個密碼。一定要 bcrypt / argon2 雜湊。

JWT

import jwt from 'jsonwebtoken';

// 簽 token
const token = jwt.sign(
  { userId: user.id },
  process.env.JWT_SECRET!,
  { expiresIn: '7d' }
);

// 驗 token(middleware)
function auth(req, res, next) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET!);
    next();
  } catch {
    res.status(401).json({ error: 'Invalid' });
  }
}

JWT 存哪?localStorage 容易被 XSS 偷。建議用 httpOnly cookie。詳細見第 13 章。

LESSON 9.6

CORS、檔案上傳、環境變數

// CORS:允許前端網域
import cors from 'cors';
app.use(cors({
  origin: ['https://my-site.com'],
  credentials: true
}));

// 檔案上傳
import multer from 'multer';
const upload = multer({
  dest: 'uploads/',
  limits: { fileSize: 5 * 1024 * 1024 }
});
app.post('/upload', upload.single('file'), (req, res) => {
  res.json({ filename: req.file.filename });
});

// 環境變數(.env)
// .env
// DATABASE_URL=postgres://...
// JWT_SECRET=xxx
import 'dotenv/config';
process.env.JWT_SECRET;

.env 永遠加進 .gitignore。把密鑰 commit 上 GitHub 是大型事故。GitHub 有 secret scanning 會通知你,但被機器人爬走通常已晚。

練習:留言板 API

用 Express 或 FastAPI 寫:

  1. POST /register 註冊(密碼 bcrypt)
  2. POST /login 簽 JWT
  3. GET /messages 列出(公開)
  4. POST /messages 發文(要 JWT)
  5. DELETE /messages/:id 只能刪自己的
  6. 用 Postman 或 curl 測試完整流程

常見卡關 FAQ

// 後端學員最常問的問題
前端 fetch 後端跳 CORS 錯誤?
後端要設 CORS。Express 用 cors 套件、FastAPI 用 CORSMiddleware。Production 要把 origin 鎖到自己的網域,不要用 *
Express 還是 Fastify 還是 Hono?
Express 最熟、文件最多。Fastify 快兩倍。Hono 最現代、可跑 Edge。新專案我推 Hono + BunNext.js API Routes
JWT 還是 Session?
JWT:無狀態、好做微服務、難撤銷。Session:要存 server、好撤銷。中小專案用 Session 或 NextAuth/Auth.js 即可。需要跨 domain / mobile 才上 JWT。
Node 還是 Python?
看用途。一般 web API 用 Node(跟前端共用)。AI、資料處理、寫爬蟲用 Python。兩個都會最強。
怎麼測 API?
Postman、Insomnia、Thunder Client(VS Code 擴充)、curl。FastAPI 內建 Swagger UI。寫測試用 vitest / pytest。
← 上一章
09 Next/Nuxt