ExpressJS (TypeScript) ─ 基礎概念與環境設定
什麼是 ExpressJS 與其架構
簡介
在 Node.js 生態系統中,ExpressJS 是最受歡迎的 Web 應用框架之一。它以極簡的 API、豐富的中介軟體(middleware)機制以及與各種資料庫、認證服務的良好相容性,成為 從小型原型到大型企業系統 都常用的選擇。
隨著 TypeScript 在前端與後端的普及,將 Express 與 TypeScript 結合,不僅能保留 Express 的開發速度,還能透過靜態型別檢查提升程式碼品質、降低執行時錯誤。了解 Express 的核心概念與底層架構,才能在日後的專案中靈活運用中介軟體、路由、錯誤處理等功能,寫出可維護、可測試的程式。
核心概念
1. Express 的基本結構
Express 本身是一個 函式,呼叫它會回傳一個 應用程式物件(app),此物件具備設定路由、使用中介軟體、啟動 HTTP 伺服器等方法。
import express, { Express, Request, Response } from "express";
const app: Express = express(); // 建立 Express 應用程式
const PORT = process.env.PORT || 3000;
// 基本路由範例
app.get("/", (req: Request, res: Response) => {
res.send("Hello, Express with TypeScript!");
});
// 啟動伺服器
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});
重點:在 TypeScript 中,我們使用
express()產生的Express型別,讓app具備完整的型別資訊,IDE 能即時提供自動完成與錯誤提示。
2. 中介軟體(Middleware)
中介軟體是 請求(request) 與 回應(response) 之間的「過濾器」或「處理器」。它可以執行日誌、驗證、解析 JSON、設定 CORS 等工作。中介軟體遵循 (req, res, next) => {} 的函式簽名,呼叫 next() 交給下一個中介軟體或路由處理器。
// 1️⃣ 內建 JSON 解析中介軟體
app.use(express.json());
// 2️⃣ 自訂日誌中介軟體
app.use((req: Request, res: Response, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
next(); // 必須呼叫 next(),否則請求會卡住
});
// 3️⃣ 錯誤處理中介軟體(必須有 4 個參數)
app.use((err: Error, req: Request, res: Response, next: Function) => {
console.error(err.stack);
res.status(500).json({ message: "Internal Server Error" });
});
技巧:將中介軟體抽成獨立檔案(例如
middlewares/logger.ts),再於app.ts中import,可以提升專案的可讀性與可測試性。
3. 路由(Routing)
路由決定 URL 與 HTTP 方法(GET、POST、PUT、DELETE…)的對應關係。Express 支援 路由參數、正則表達式、以及 路由群組(Router),讓 API 結構更清晰。
// 單一路由範例
app.get("/users/:id", (req: Request, res: Response) => {
const userId = req.params.id;
// 假設從資料庫取得使用者資料
res.json({ id: userId, name: "John Doe" });
});
// 使用 Router 建立模組化路由
import { Router } from "express";
const productRouter = Router();
productRouter.get("/", (req, res) => {
res.json([{ id: 1, name: "Keyboard" }]);
});
productRouter.post("/", (req, res) => {
const newProduct = req.body;
// 儲存新商品…
res.status(201).json(newProduct);
});
// 把 Router 掛載到 /api/products
app.use("/api/products", productRouter);
說明:
Router本身也是一個 mini‑Express 應用程式,適合把 CRUD、驗證、授權 等功能分層管理。
4. 錯誤處理(Error Handling)
Express 的錯誤處理機制與一般中介軟體略有不同:必須多一個 err 參數,且放在所有路由與中介軟體之後。透過統一的錯誤處理器,我們可以將錯誤訊息格式化、記錄日誌或回傳適當的 HTTP 狀態碼。
// 產生自訂錯誤類別
class HttpError extends Error {
status: number;
constructor(status: number, message: string) {
super(message);
this.status = status;
}
}
// 在路由中拋出錯誤
app.get("/admin", (req, res, next) => {
const isAdmin = false; // 假設驗證失敗
if (!isAdmin) return next(new HttpError(403, "Forbidden"));
res.send("Welcome admin");
});
// 統一錯誤處理器
app.use((err: HttpError, req: Request, res: Response, next: Function) => {
const status = err.status || 500;
res.status(status).json({ error: err.message });
});
5. TypeScript 整合要點
| 功能 | TypeScript 實作方式 | 目的 |
|---|---|---|
| 型別安全的 Request/Response | import { Request, Response } from "express" |
提供 req.body、req.params 等屬性的型別 |
| 自訂型別(例如擴充 req.user) | declare global { namespace Express { interface Request { user?: User } } } |
在認證中介軟體加入使用者資訊 |
| 環境變數 | import dotenv from "dotenv"; dotenv.config(); |
透過 .env 檔管理設定,型別可用 process.env.PORT as string |
| 自動產生型別的中介軟體 | 使用 express-validator + TypedRequestBody<T> |
確保驗證後的資料符合介面定義 |
常見陷阱與最佳實踐
| 常見陷阱 | 說明 | 最佳實踐 |
|---|---|---|
忘記呼叫 next() |
中介軟體未傳遞控制權,請求會卡住 | 每個非結束回應的中介軟體最後一定 next() |
| 在同一檔案寫太多路由 | 檔案膨脹、維護困難 | 使用 Router 分割功能模組(user、product、auth) |
直接使用 any |
失去 TypeScript 的型別保護 | 定義介面或型別別名,盡量避免 any |
| 錯誤處理器位置錯誤 | 放在路由前面會導致錯誤不被捕捉 | 必須 最後 註冊錯誤處理中介軟體 |
| 未設定 CORS | 前端跨域請求被阻擋 | 使用 cors 套件,並在環境變數中設定允許來源 |
其他最佳實踐
- 使用
dotenv管理環境變數,並在tsconfig.json中啟用esModuleInterop。 - 將型別定義集中管理(如
src/types/*.d.ts),避免重複。 - 加入單元測試(Jest + SuperTest),確保路由與中介軟體行為正確。
- 遵循 RESTful 原則:統一資源路徑、使用正確的 HTTP 狀態碼。
- 在生產環境使用
helmet加強 HTTP 標頭安全。
實際應用場景
| 場景 | 為何選擇 Express + TypeScript |
|---|---|
| 微服務 API | 輕量、快速開發,型別保證讓跨團隊協作更安全 |
| Server‑Side Rendering (SSR) 與 Next.js 結合 | Express 可作為自訂伺服器,處理 API 與頁面渲染的分工 |
| IoT 資料收集平台 | 中介軟體可輕鬆實作驗證、限流、日誌,支援大量短連線 |
| 企業內部管理系統 | 透過 Router + Role‑Based Access Control(RBAC)快速構建權限系統 |
| 即時聊天或遊戲伺服器 | 搭配 socket.io,Express 處理 HTTP API,Socket 處理 WebSocket 連線 |
總結
ExpressJS 以 簡潔的核心 API、彈性的中介軟體機制,成為 Node.js 生態中最常見的 Web 框架。結合 TypeScript 後,我們不僅保留了 Express 的開發速度,還能透過 靜態型別、IDE 提示、編譯期錯誤檢查,提升程式碼品質與可維護性。
掌握 應用程式物件、Middleware、Router、Error Handling 四大基石,並遵守 最佳實踐(如分層路由、型別安全、環境變數管理),即可在各種實務場景中快速建立可靠的 API 服務。未來進一步學習 測試、效能優化、部署,將讓你從「入門」走向「專家」的完整路徑。祝開發順利,寫出乾淨、可讀、可測的 Express + TypeScript 程式!