用 Vercel、TiDB Cloud 和 Cloudflare R2 部署朋友圈博客 pyq
用 Vercel、TiDB Cloud 和 Cloudflare R2 部署朋友圈博客 pyq
这是一篇部署记录,整理了本次把开源项目 zhjurz/pyq 部署为在线博客的主要过程。文中只保留架构、步骤和公开访问地址,已去除 API Key、数据库密码、Token、私钥、数据库账号等敏感信息。
项目简介
pyq 是一个类似朋友圈形态的个人博客项目,前后端分离:
前端:Next.js,部署到 Vercel;
后端:Node.js / Express / Sequelize,部署到 Vercel Serverless;
数据库:MySQL 协议兼容数据库,本次使用 TiDB Cloud 免费/开发规格;
媒体存储:Cloudflare R2,用于图片、音频等对象存储。
最终访问地址:
博客前端:https://pyq-blog-frontend.vercel.app
后端健康检查:https://pyq-blog-backend.vercel.app/api/health
部署架构
用户浏览器
↓
Vercel Frontend / Next.js
↓ /api rewrite
Vercel Backend / Express API
├─ TiDB Cloud:保存文章、用户、评论、点赞等数据
└─ Cloudflare R2:保存上传媒体文件
这样部署的好处是:
前端和后端都可以用 Vercel 托管,更新方便;
TiDB Cloud 兼容 MySQL 协议,适合 Sequelize / mysql2 这类项目;
R2 适合保存博客媒体文件,避免把上传文件放在 Serverless 本地磁盘;
后续绑定自定义域名时,只需要分别给前端、后端、媒体域名做映射即可。
主要部署步骤
1. 检查项目结构
先拉取项目源码,确认它不是单体应用,而是包含:
frontend/ # Next.js 前端
backend/ # Express 后端
后端需要以下关键环境变量:
DB_HOST=数据库地址
DB_PORT=数据库端口
DB_USER=数据库用户
DB_PASSWORD=数据库密码
DB_NAME=数据库名
DB_SSL=true
JWT_SECRET=随机长字符串
REVALIDATE_SECRET=随机长字符串
R2_ACCOUNT_ID=Cloudflare Account ID
R2_ACCESS_KEY_ID=R2 Access Key
R2_SECRET_ACCESS_KEY=R2 Secret Key
R2_BUCKET=Bucket 名称
R2_PUBLIC_URL=公开媒体访问域名
CLIENT_URL=前端访问地址
CORS_ALLOWED_ORIGINS=允许跨域的前端地址
前端需要:
BACKEND_URL=后端地址
NEXT_PUBLIC_API_URL=/api
NEXT_PUBLIC_MEDIA_ORIGIN=媒体公开域名
NEXT_PUBLIC_SITE_URL=前端站点地址
REVALIDATE_SECRET=与后端一致的重建密钥
实际部署时,这些值已通过 Vercel 环境变量配置;敏感值没有写入本文。
2. 创建 TiDB Cloud 数据库
由于项目使用 MySQL 协议,本次选择 TiDB Cloud 的免费/开发规格集群。
过程概括:
创建 TiDB Cloud API Key;
使用 TiDB Cloud API 创建 DEVELOPER 规格集群;
等待集群状态变为 AVAILABLE;
创建项目数据库 moment_blog;
运行项目自带初始化脚本,创建数据表和默认数据。
本次数据库采用:
Cloud Provider: AWS
Region: ap-southeast-1
Database: moment_blog
SSL: enabled
3. 创建 Cloudflare R2 媒体存储
创建了一个新的 R2 Bucket 用于保存博客媒体文件,并启用了公开访问域名。
部署中用到的公开媒体域名形态类似:
https://pub-xxxxx.r2.dev
R2 负责保存上传图片、音频等文件;数据库只保存文件 URL 和元数据。
4. 初始化后端数据库
在后端目录安装依赖后,先创建数据库,再执行项目自带初始化脚本:
npm install
npm run db:init
初始化完成后,数据库中会生成用户、文章、评论、站点配置等基础表结构。
5. 创建并部署 Vercel 后端项目
后端作为独立 Vercel 项目部署,项目名为:
pyq-blog-backend
部署时配置了数据库、JWT、R2、前端 CORS 等环境变量。部署完成后,健康检查接口返回:
{"status":"ok"}
公开健康检查地址:
https://pyq-blog-backend.vercel.app/api/health
6. 创建并部署 Vercel 前端项目
前端作为独立 Vercel 项目部署,项目名为:
pyq-blog-frontend
前端通过 /api rewrite 访问后端,部署完成后访问:
https://pyq-blog-frontend.vercel.app
返回正常 HTML 页面,说明前端部署成功。
7. 验证部署
最后分别验证:
后端健康检查:200 OK
前端首页:200 OK
前端 /api/health 代理:200 OK
说明:
Vercel 前端可访问;
Vercel 后端可访问;
前端到后端的 API rewrite 正常;
后端到 TiDB Cloud 数据库连接正常。
本次部署结果
公开访问地址:
博客首页:https://pyq-blog-frontend.vercel.app
后端健康检查:https://pyq-blog-backend.vercel.app/api/health
使用到的云资源:
Vercel:前端项目、后端项目;
TiDB Cloud:MySQL 兼容数据库;
Cloudflare R2:媒体对象存储。
后续可优化项
绑定自定义域名,例如:
- blog.example.com 指向前端;
- api-blog.example.com 指向后端;
- media-blog.example.com 指向 R2。
修改默认管理员密码,避免继续使用初始化默认密码。
给数据库和 R2 做周期性备份或导出。
将部署脚本整理为可重复执行的脚本,方便以后更新项目。
配置更严格的 CORS 和访问控制,只允许正式域名访问。
小结
这次部署的关键点是把 pyq 拆成前端、后端、数据库、对象存储四部分分别托管:
Next.js 前端 → Vercel
Express 后端 → Vercel
MySQL 兼容数据库 → TiDB Cloud
媒体文件 → Cloudflare R2
这种方案成本低、维护简单,适合个人博客、小型朋友圈站点和轻量内容系统。