Giao diện
Kiến trúc
Toàn bộ hệ thống chạy trên hạ tầng biên của Cloudflare; không có máy chủ nào cần trực.
┌──────────────────────────┐
Trình duyệt ───▶ │ www.chuyenchon.com │
│ Cloudflare Pages │
│ HTML tĩnh + SPA React │
└───────────┬──────────────┘
│ fetch /v1/* (CORS)
▼
┌──────────────────────────┐
│ api.chuyenchon.com │
│ Cloudflare Worker (Hono)│
└───────────┬──────────────┘
│ binding DB
▼
┌──────────────────────────┐
│ Cloudflare D1 (SQLite) │
│ bảng thực thể + FTS5 │
└──────────────────────────┘
docs.chuyenchon.com — Cloudflare Pages (VitePress), độc lập hoàn toànVì sao tách API thành Worker riêng
Có thể đặt /api/* ngay trong Pages Functions, nhưng tách ra đem lại:
- Một tên miền ổn định cho mọi client về sau (web, ứng dụng di động, đối tác) — đúng vai trò "API Gateway" trong đề bài.
- Vòng đời triển khai độc lập: sửa truy vấn không cần build lại toàn bộ frontend.
- Bước prerender gọi được API như một client bên ngoài — chính là điều cần để sinh HTML tĩnh.
Chi phí phải trả là CORS, xử lý ở src/index.ts bằng danh sách ALLOWED_ORIGINS.
Ba tầng dữ liệu
| Tầng | Nơi chạy | Trách nhiệm |
|---|---|---|
| D1 | Cloudflare | Lưu trữ, ràng buộc, chỉ mục FTS5 |
| Worker | Biên | Lọc, phân trang, ghép quan hệ, đặt Cache-Control |
| Trình duyệt | Máy người dùng | TanStack Query giữ cache trong phiên, hydrate từ HTML tĩnh |
Worker đặt Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=86400 cho dữ liệu công khai, nên phần lớn request được phục vụ từ cache biên chứ không chạm D1.
Ngân sách hiệu năng
- Mỗi endpoint chi tiết dùng một
db.batch()thay vì nhiều lượt truy vấn nối tiếp. - Danh sách luôn có
LIMIT,per_pagechặn trần ở 100. - Chỉ mục tìm kiếm dựng sẵn (bảng
search_docs+search_fts) thay vìLIKEtrên nhiều bảng.
Biến môi trường
| Biến | Nơi dùng | Ghi chú |
|---|---|---|
ALLOWED_ORIGINS | Worker | Danh sách origin, phân tách bằng dấu phẩy |
ADMIN_TOKEN | Worker (secret) | Bearer token cho /v1/admin/* |
VITE_API_BASE | Web (build) | Gốc API; để trống khi dev để dùng proxy của Vite |
VITE_SITE_URL | Web (build) | Dùng cho canonical và sitemap |