从零到部署:使用 Vercel 部署前端、Render 部署后端的完整实操手册 ,其中用到的实例皆是本人个人项目实战demo,部署后前端地址
📋 目录
- 部署架构概览
- 前置准备
- [第一步:部署后端到 Render](#第一步:部署后端到 Render "#3-%E7%AC%AC%E4%B8%80%E6%AD%A5%E9%83%A8%E7%BD%B2%E5%90%8E%E7%AB%AF%E5%88%B0-render")
- 第二步:初始化数据库
- [第三步:部署前端到 Vercel](#第三步:部署前端到 Vercel "#5-%E7%AC%AC%E4%B8%89%E6%AD%A5%E9%83%A8%E7%BD%B2%E5%89%8D%E7%AB%AF%E5%88%B0-vercel")
- [第四步:部署后台管理到 Vercel](#第四步:部署后台管理到 Vercel "#6-%E7%AC%AC%E5%9B%9B%E6%AD%A5%E9%83%A8%E7%BD%B2%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E5%88%B0-vercel")
- 第五步:连接前后端
- 第六步:验证部署
- [Monorepo 特殊配置说明](#Monorepo 特殊配置说明 "#9-monorepo-%E7%89%B9%E6%AE%8A%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E")
- 环境变量完整清单
- 免费额度说明
- 常见问题排查
- 优化建议
- 持续部署(CI/CD)
1. 部署架构概览
部署架构图
scss
┌─────────────────────────────────────────────────────────────┐
│ 用户访问 │
└──────────────────┬──────────────────┬───────────────────────┘
│ │
┌─────────▼──────────┐ ┌───▼──────────────┐
│ Vercel (前端) │ │ Vercel (后台) │
│ blog-frontend │ │ blog-admin │
│ 静态资源 + SPA │ │ 管理界面 │
└─────────┬──────────┘ └───┬──────────────┘
│ │
│ API 请求 (/api) │
│ │
┌─────────▼──────────────────▼──────────────┐
│ Render (后端) │
│ blog-server │
│ Node.js + Express │
│ (https://blog-2eqo.onrender.com) │
└─────────┬─────────────────────────────────┘
│
│ PostgreSQL
│
┌─────────▼─────────────────────────────────┐
│ Render PostgreSQL │
│ blog-postgres │
│ Database: blog_system │
└───────────────────────────────────────────┘
技术栈
| 组件 | 平台 | 技术栈 | 费用 |
|---|---|---|---|
| 前端 | Vercel | React + Rsbuild + Ant Design | 免费 |
| 后台管理 | Vercel | React + Rsbuild + Ant Design + Draft.js | 免费 |
| 后端 API | Render | Node.js + Express + TypeScript | 免费 |
| 数据库 | Render | PostgreSQL 16 | 免费 |
部署顺序
⚠️ 重要:必须按以下顺序部署,因为前端需要后端 API 的 URL:
- 后端 → Render (获取 API URL)
- 数据库初始化 → Render Shell
- 前端 → Vercel (配置 API 代理)
- 后台 → Vercel (配置 API 代理)
- 连接测试 → 更新 CORS 配置
2. 前置准备
2.1 GitHub 仓库准备
确保你的项目代码已推送到 GitHub:
bash
cd /path/to/blog
git status
git add .
git commit -m "feat: prepare for deployment"
git push origin main
2.2 账号注册
Render 注册:
- 访问 render.com
- 点击 "Get Started" → "Sign Up with GitHub"
- 授权 Render 访问你的 GitHub 仓库
- ✅ 无需信用卡,完全免费
Vercel 注册:
- 访问 vercel.com
- 点击 "Sign Up" → "Continue with GitHub"
- 授权 Vercel 访问你的 GitHub 仓库
- ✅ 无需信用卡,完全免费
2.3 环境检查
确认项目包含以下文件:
bash
# Render 配置
packages/blog-server/render.yaml ✅
packages/blog-server/.env.render.example ✅
# Vercel 配置
packages/blog-frontend/vercel.json ✅
packages/blog-admin/vercel.json ✅
# 数据库初始化
packages/blog-server/database/init.sql ✅
packages/blog-server/scripts/init-database.ts ✅
3. 第一步:部署后端到 Render
3.1 创建 PostgreSQL 数据库
-
点击右上角 "New +" → 选择 "PostgreSQL"
-
填写数据库配置:
字段 值 Name blog-postgresDatabase blog_systemUser blog_user(自动生成,可修改)Region 选择 Singapore(离中国最近) PostgreSQL Version 16(默认) Plan Free -
点击 "Create Database"
-
等待约 1-2 分钟,状态变为 "Available"
-
保存连接信息(稍后需要):
- 进入数据库 → "Info" 标签
- 记录:
- Hostname (例如:
dpg-xxxx-a.singapore-postgres.render.com) - Port (通常是
5432) - Database (
blog_system) - Username (
blog_user) - Password(自动生成的长密码)
- Hostname (例如:
3.2 创建 Web Service(后端 API)
-
在 Render Dashboard,点击 "New +" → "Web Service"
-
点击 "Build and deploy from a Git repository" → "Next"
-
选择你的 GitHub 仓库
blog(如果没有显示,点击 "Configure account" 授权) -
填写服务配置:
字段 值 说明 Name blog-server服务名称 Region Singapore 与数据库同区域 Branch mainGit 分支 Root Directory packages/blog-server⚠️ 重要:Monorepo 子目录 Runtime Node 自动检测 Build Command npm install && npm run build安装依赖并编译 TypeScript Start Command npm start启动服务 Plan Free 免费计划 -
点击 "Advanced" 展开高级选项(暂不配置,稍后添加环境变量)
-
点击 "Create Web Service"
⏳ 构建过程:约 3-5 分钟,在 "Logs" 标签查看进度
3.3 配置环境变量
构建完成后(状态显示 "Live" 或 "Deploy failed",先别管),配置环境变量:
-
在 Web Service 页面,点击 "Environment" 标签
-
点击 "Add Environment Variable",逐个添加以下变量:
基础配置
bash
NODE_ENV=production
JWT 配置
bash
JWT_SECRET=51de2d30c5629597bf6f41dbcf9f41beb714bb31e91adb5899d25fce64202fd9
💡 生产环境必须修改:使用以下命令生成新密钥:
bashnode -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
bash
JWT_EXPIRES_IN=7d
CORS 配置(稍后更新)
bash
FRONTEND_URL=https://your-frontend.vercel.app
bash
ADMIN_URL=https://your-admin.vercel.app
⚠️ 注意:这两个 URL 在部署 Vercel 后需要更新为实际 URL
文件上传配置
bash
MAX_FILE_SIZE=5242880
bash
ALLOWED_IMAGE_TYPES=image/jpeg,image/png,image/gif,image/webp
数据库配置(从步骤 3.1 复制)
bash
DB_HOST=<从数据库 Info 复制 Hostname>
bash
DB_PORT=5432
bash
DB_USER=<从数据库 Info 复制 Username>
bash
DB_PASSWORD=<从数据库 Info 复制 Password>
bash
DB_NAME=blog_system
-
点击 "Save Changes"
-
Render 会自动触发重新部署(约 2 分钟)
3.4 查看部署日志
- 在 "Logs" 标签,确认看到以下内容:
dart
🚀 Server is running on http://0.0.0.0:10000
📝 Environment: production
🗄️ Database: blog_system@dpg-xxxx.singapore-postgres.render.com:5432
- 如果看到错误,检查环境变量是否正确
3.5 获取 API URL
-
在 Web Service 顶部,复制服务 URL:
arduinohttps://blog-server-xxxx.onrender.com -
保存这个 URL,稍后部署前端时需要
-
测试 API(可选):
bash# 健康检查 curl https://blog-server-xxxx.onrender.com/api/health # 获取分类(应该返回空数组,因为数据库未初始化) curl https://blog-server-xxxx.onrender.com/api/categories
4. 第二步:初始化数据库
4.1 使用 Render Shell
-
在 Web Service 页面,点击 "Shell" 标签
-
点击 "Launch Shell" 按钮
-
等待 Shell 启动(约 10 秒)
-
在 Shell 中运行初始化脚本:
bashnpm run db:init -
成功后会看到:
yaml🚀 Starting database initialization... ✅ Connected to database ✅ Tables created successfully ✅ Seed data inserted successfully ✅ Admin user created successfully 🎉 Database initialization complete! 📝 Admin credentials: Username: admin Password: admin123 Email: admin@blog.com
4.2 验证数据
在 Shell 中运行:
bash
# 进入 PostgreSQL(如果需要)
psql $DATABASE_URL
# 查看所有表
\dt
# 查看分类
SELECT * FROM categories;
# 查看管理员
SELECT username, email FROM admin_users;
# 退出
\q
应该看到:
- 4 张表:
admin_users,categories,articles,images - 8 个分类(前端开发、后端开发等)
- 1 个管理员账号
5. 第三步:部署前端到 Vercel
5.1 导入项目
-
点击 "Add New..." → "Project"
-
选择你的 GitHub 仓库
blog -
点击 "Import"
5.2 配置项目(blog-frontend)
Vercel 会自动检测到 Monorepo 结构,现在配置前端:
| 字段 | 值 | 说明 |
|---|---|---|
| Project Name | blog-frontend(可自定义) |
项目名称 |
| Framework Preset | Other | 不使用预设 |
| Root Directory | packages/blog-frontend |
⚠️ 重要:点击 "Edit" 修改 |
| Build Command | npm install && cd packages/blog-frontend && npm run build |
⚠️ Monorepo 构建命令 |
| Output Directory | ../../dist/packages/blog-frontend |
构建输出目录 |
| Install Command | npm install --prefix ../.. && npm install |
安装依赖 |
配置截图说明位置
Root Directory 配置:
- 在 "Build and Output Settings" 下找到 "Root Directory"
- 点击 "Edit" 按钮
- 选择
packages/blog-frontend
Build Command 配置:
- 勾选 "Override" 复选框
- 输入完整的 Monorepo 构建命令
5.3 配置 API 重写(重要)
⚠️ Vercel 项目配置会读取 vercel.json,但我们手动确认一下:
- 在部署前,确认项目根目录的
packages/blog-frontend/vercel.json包含:
json
{
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://blog-server-xxxx.onrender.com/api/:path*"
},
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}
-
⚠️ 重要 :将
https://blog-server-xxxx.onrender.com替换为你在步骤 3.5 获取的实际 Render URL -
如果已修改,提交代码:
bash
git add packages/blog-frontend/vercel.json
git commit -m "fix: update API URL in vercel.json"
git push origin main
5.4 部署
-
配置完成后,点击 "Deploy"
-
⏳ 构建时间:约 2-3 分钟
-
成功后会显示:
✅ Deployment Ready -
点击 "Visit" 或复制部署 URL(例如:
https://blog-frontend-xxxx.vercel.app) -
保存前端 URL,稍后需要更新 Render 的 CORS 配置
5.5 验证前端部署
访问前端 URL,应该看到:
- ✅ 博客首页加载正常
- ✅ 分类列表显示(从 Render API 获取)
- ⚠️ 可能显示 "暂无文章"(正常,因为还没创建文章)
6. 第四步:部署后台管理到 Vercel
6.1 部署流程
与前端类似,重复步骤 5,但使用不同的配置:
-
在 Vercel Dashboard,点击 "Add New..." → "Project"
-
再次选择
blog仓库 -
Vercel 会提示 "This repository is already connected",选择 "Import Anyway"
-
配置项目:
| 字段 | 值 |
|---|---|
| Project Name | blog-admin |
| Framework Preset | Other |
| Root Directory | packages/blog-admin |
| Build Command | npm install && cd packages/blog-admin && npm run build |
| Output Directory | ../../dist/packages/blog-admin |
| Install Command | npm install --prefix ../.. && npm install |
-
确认
packages/blog-admin/vercel.json中的 API URL 与前端一致 -
点击 "Deploy"
-
获取后台 URL(例如:
https://blog-admin-xxxx.vercel.app)
6.2 验证后台部署
访问后台 URL,应该看到:
- ✅ 登录页面加载正常
- ⚠️ 先不要登录(CORS 还未配置)
7. 第五步:连接前后端
7.1 更新 Render 的 CORS 配置
现在我们有了前端和后台的 URL,需要更新 Render 环境变量:
-
回到 Render Dashboard →
blog-server服务 -
进入 "Environment" 标签
-
更新以下变量:
bashFRONTEND_URL=https://blog-frontend-xxxx.vercel.appbashADMIN_URL=https://blog-admin-xxxx.vercel.app替换为你实际的 Vercel URL
-
点击 "Save Changes"
-
Render 会自动重启服务(约 1 分钟)
7.2 测试 API 连接
-
打开浏览器控制台(F12)
-
访问前端 URL:
https://blog-frontend-xxxx.vercel.app -
在 Network 标签查看 API 请求:
- ✅ 应该看到
/api/categories请求成功 - ✅ 响应头包含
Access-Control-Allow-Origin
- ✅ 应该看到
-
如果看到 CORS 错误,检查:
- Render 环境变量是否正确
- 服务是否已重启
- URL 是否包含
https://
7.3 验证登录功能
-
访问后台 URL:
https://blog-admin-xxxx.vercel.app -
使用默认账号登录:
- 用户名 :
admin - 密码 :
admin123
- 用户名 :
-
登录成功后,应该进入 Dashboard
-
查看:
- ✅ 分类列表显示
- ✅ 文章列表为空(正常)
- ✅ 可以创建新文章
8. 第六步:验证部署
8.1 测试前端访问
bash
# 替换为你的前端 URL
FRONTEND_URL="https://blog-frontend-xxxx.vercel.app"
# 测试首页
curl -I $FRONTEND_URL
# 应该返回 200 OK
# 测试 API 代理
curl $FRONTEND_URL/api/categories
# 应该返回 JSON 分类列表
8.2 测试后台登录
-
打开浏览器控制台
-
访问
https://blog-admin-xxxx.vercel.app -
输入账号密码,点击登录
-
在 Network 标签查看:
- ✅
/api/auth/login请求成功(200) - ✅ 返回
token和用户信息 - ✅ 自动跳转到 Dashboard
- ✅
8.3 测试 API 调用
bash
# 替换为你的后端 URL
API_URL="https://blog-server-xxxx.onrender.com"
# 测试健康检查
curl $API_URL/api/health
# 返回: {"status":"ok","timestamp":"..."}
# 测试获取分类
curl $API_URL/api/categories
# 返回: {"code":0,"message":"success","data":[...]}
# 测试登录
curl -X POST $API_URL/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
# 返回: {"code":0,"message":"Login successful","data":{"token":"...","user":{...}}}
8.4 测试图片上传
-
登录后台管理
-
进入 "文章管理" → "创建文章"
-
点击上传封面图片
-
选择一张图片(<5MB)
-
确认:
- ✅ 上传成功
- ✅ 图片预览显示
- ✅ 发布文章后,前端可以看到图片
9. Monorepo 特殊配置说明
9.1 为什么需要特殊的构建命令?
项目使用 Nx Monorepo,所有 packages 共享根目录的 node_modules:
bash
blog/
├── node_modules/ # 根依赖
├── packages/
│ ├── blog-frontend/
│ │ ├── node_modules/ # 子项目依赖
│ │ └── package.json
│ └── blog-server/
│ └── ...
└── package.json # 根 package.json
9.2 Vercel 构建命令解析
标准命令:
bash
npm install && cd packages/blog-frontend && npm run build
分解:
npm install- 安装根依赖(Nx, TypeScript 等)cd packages/blog-frontend- 进入前端目录npm run build- 构建前端(Rsbuild)
9.3 输出目录配置
为什么是 ../../dist/packages/blog-frontend?
- Vercel 从
packages/blog-frontend目录开始 - 输出到
../../dist/packages/blog-frontend(相对于当前目录) - 实际路径:
blog/dist/packages/blog-frontend
rsbuild.config.ts 配置:
typescript
output: {
distPath: {
root: '../../dist/packages/blog-frontend'
}
}
9.4 API 代理重写机制
vercel.json 配置:
json
{
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://blog-2eqo.onrender.com/api/:path*"
}
]
}
工作原理:
- 前端发起请求:
/api/articles - Vercel 拦截请求,重写为:
https://blog-2eqo.onrender.com/api/articles - 转发到 Render 后端
- 返回响应给前端
优点:
- ✅ 前端无需关心 API 域名
- ✅ 避免 CORS 问题(同域请求)
- ✅ 简化环境变量管理
10. 环境变量完整清单
10.1 Render 环境变量(blog-server)
| 变量名 | 值 | 说明 |
|---|---|---|
NODE_ENV |
production |
生产环境标识 |
JWT_SECRET |
<随机 64 位字符串> |
JWT 签名密钥(必须修改) |
JWT_EXPIRES_IN |
7d |
Token 过期时间 |
FRONTEND_URL |
https://blog-frontend-xxxx.vercel.app |
前端 URL(CORS) |
ADMIN_URL |
https://blog-admin-xxxx.vercel.app |
后台 URL(CORS) |
DB_HOST |
<Render 数据库 Hostname> |
数据库主机 |
DB_PORT |
5432 |
数据库端口 |
DB_USER |
<Render 数据库 Username> |
数据库用户 |
DB_PASSWORD |
<Render 数据库 Password> |
数据库密码 |
DB_NAME |
blog_system |
数据库名称 |
MAX_FILE_SIZE |
5242880 |
最大文件大小(5MB) |
ALLOWED_IMAGE_TYPES |
image/jpeg,image/png,image/gif,image/webp |
允许的图片类型 |
10.2 Vercel 环境变量(可选)
blog-frontend 和 blog-admin:
| 变量名 | 值 | 说明 |
|---|---|---|
VITE_API_BASE_URL |
<Render API URL>/api |
API 基础 URL(可选) |
注意 :由于使用了
vercel.json的rewrites,前端可以直接用/api请求,无需配置环境变量。
10.3 安全性建议
生成安全的 JWT_SECRET
bash
# 方法 1:Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# 方法 2:OpenSSL
openssl rand -hex 32
# 方法 3:在线工具
# https://www.uuidgenerator.net/
环境变量管理
- ⚠️ 永远不要 把
.env提交到 Git - ✅ 使用
.env.example作为模板 - ✅ 生产环境的密钥与开发环境不同
- ✅ 定期轮换 JWT_SECRET(需要用户重新登录)
11. 免费额度说明
11.1 Vercel 免费计划
| 项目 | 额度 | 说明 |
|---|---|---|
| 带宽 | 100 GB/月 | 足够个人博客使用 |
| 构建执行时间 | 100 GB-小时/月 | 约 100 次构建 |
| 部署数量 | 无限 | 每次 push 都会部署 |
| 项目数量 | 无限 | 可以部署多个项目 |
| 团队成员 | 1 人 | 免费计划仅支持个人 |
| 域名 | 自定义域名 | 支持绑定自己的域名 |
限制:
- 每次构建最多 45 分钟
- 无服务器函数最多运行 10 秒
- 环境变量最多 4KB
足够用于:
- ✅ 个人博客
- ✅ 小型项目展示
- ✅ 前端应用
- ⚠️ 不适合高流量商业网站
11.2 Render 免费计划
| 项目 | 额度 | 说明 |
|---|---|---|
| 运行时间 | 750 小时/月 | 约 31 天,够用一整月 |
| 内存 | 512 MB | 足够 Node.js 应用 |
| CPU | 共享 | 性能受限,但可接受 |
| 带宽 | 100 GB/月 | 出站流量限制 |
| 构建时间 | 每次 500 秒 | 足够 npm install + build |
| PostgreSQL | 256 MB 存储 | 约可存储 10000+ 篇文章 |
重要限制:
- ⚠️ 服务会在 15 分钟无活动后休眠
- ⚠️ 从休眠唤醒需要 30-50 秒(首次访问慢)
- ⚠️ PostgreSQL 数据库 90 天未访问会被删除
- ✅ 数据库不会休眠(始终在线)
足够用于:
- ✅ 个人博客后端
- ✅ API 服务
- ✅ 小型全栈应用
- ⚠️ 不适合需要即时响应的应用
11.3 如何应对 Render 休眠?
方法 1:使用 UptimeRobot(推荐)
- 注册 uptimerobot.com(免费)
- 添加 Monitor:
- Monitor Type: HTTP(s)
- URL :
https://blog-server-xxxx.onrender.com/api/health - Monitoring Interval: 5 分钟
- UptimeRobot 会每 5 分钟 ping 一次,保持服务唤醒
方法 2:使用 Cron-job.org
- 注册 cron-job.org
- 创建定时任务:
- URL :
https://blog-server-xxxx.onrender.com/api/health - Execution: 每 10 分钟
- URL :
方法 3:前端定时请求(不推荐)
在前端添加定时器:
javascript
// 不推荐:消耗用户带宽
setInterval(() => {
fetch('/api/health')
}, 5 * 60 * 1000) // 每 5 分钟
12. 常见问题排查
12.1 API 502/504 错误
症状:前端显示 "网络错误" 或 "502 Bad Gateway"
原因:Render 服务休眠,正在唤醒
解决方案:
-
等待 30-50 秒,刷新页面
-
如果仍然失败,检查 Render 服务状态:
- 进入 Render Dashboard →
blog-server - 查看 "Logs" 是否有错误
- 确认服务状态为 "Live"
- 进入 Render Dashboard →
-
如果服务启动失败,检查:
bash# 在 Render Shell 中 node dist/server.js # 查看错误信息
12.2 CORS 错误
症状:浏览器控制台显示:
rust
Access to fetch at 'https://blog-xxxx.onrender.com/api/...'
from origin 'https://blog-frontend-xxxx.vercel.app' has been blocked by CORS policy
原因 :Render 环境变量中的 FRONTEND_URL 或 ADMIN_URL 不正确
解决方案:
-
检查 Render 环境变量:
FRONTEND_URL必须与 Vercel 前端 URL 完全一致- 包含
https:// - 不包含尾部斜杠
/
-
确认 CORS 配置(
packages/blog-server/src/middleware/cors.ts):typescriptorigin: [ env.FRONTEND_URL, // 前端 URL env.ADMIN_URL // 后台 URL ] -
重启 Render 服务(修改环境变量后自动重启)
12.3 Vercel 构建失败
症状:Vercel 部署失败,显示 "Build failed"
常见错误 1:找不到模块
arduino
Error: Cannot find module 'react'
解决方案:
- 检查 Build Command 是否包含
npm install - 确认 Root Directory 配置正确
常见错误 2:输出目录为空
javascript
Error: No Output Directory named "dist" found after the build
解决方案:
- 检查 Output Directory 配置:
../../dist/packages/blog-frontend - 本地运行
npm run build确认输出目录正确
常见错误 3:构建超时
csharp
Error: Command timed out after 45 minutes
解决方案:
- 检查
package.json是否有重复依赖 - 使用
npm ci代替npm install(更快)
12.4 数据库连接失败
症状:Render 日志显示:
arduino
Error: connect ETIMEDOUT
原因:数据库环境变量配置错误
解决方案:
-
检查 Render 环境变量:
DB_HOST、DB_PORT、DB_USER、DB_PASSWORD、DB_NAME- 与数据库 "Info" 标签的信息一致
-
确认数据库状态为 "Available"
-
测试连接(在 Render Shell):
bashpsql $DATABASE_URL -c "SELECT 1"
12.5 图片显示 404
症状:前端文章列表或详情页,封面图片显示 404
原因:数据库未初始化,或图片未上传
解决方案:
-
确认数据库已初始化:
bash# 在 Render Shell psql $DATABASE_URL -c "SELECT COUNT(*) FROM images" -
如果表不存在,运行:
bashnpm run db:init -
上传测试图片:
- 登录后台管理
- 创建文章并上传封面
12.6 登录失败
症状:输入账号密码后,提示 "用户名或密码错误"
原因:管理员账号未创建
解决方案:
-
检查数据库中的管理员:
bash# 在 Render Shell psql $DATABASE_URL -c "SELECT username, email FROM admin_users" -
如果为空,重新初始化:
bashnpm run db:init -
或手动创建管理员:
bashnpm run create-admin
13. 优化建议
13.1 防止 Render 休眠
使用 UptimeRobot 定期 ping API(推荐):
- 注册 uptimerobot.com
- 添加 HTTP Monitor
- URL:
https://blog-server-xxxx.onrender.com/api/health - 间隔: 5 分钟
效果:
- ✅ 服务始终保持活跃
- ✅ 用户访问无需等待唤醒
- ✅ 免费,无需额外成本
13.2 图片优化
问题:图片存储在数据库中,占用空间且加载慢
优化方案:
-
压缩图片(前端上传前)
- 使用
browser-image-compression库 - 限制宽度 1200px,质量 80%
- 使用
-
迁移到对象存储(推荐)
- 使用 Cloudflare R2(免费 10GB)
- 或 AWS S3 + CloudFront
- 数据库只存储 URL
-
添加图片缓存
- Vercel 自动缓存静态资源
- 后端添加
Cache-Control头
13.3 性能监控
Vercel Analytics(免费):
- 进入 Vercel 项目 → "Analytics"
- 启用 Web Analytics
- 查看:
- 页面加载时间
- 用户访问量
- 地理分布
Render Metrics(免费):
- 进入 Render 服务 → "Metrics"
- 查看:
- CPU 使用率
- 内存使用率
- HTTP 请求量
13.4 数据库备份
Render 免费计划不提供自动备份,建议手动备份:
bash
# 本地备份
pg_dump "<External Database URL>" > backup.sql
# 恢复
psql "<External Database URL>" < backup.sql
定期备份:
- 每周备份一次
- 存储在 GitHub(加密)或 Google Drive
13.5 日志管理
Winston 日志配置(已集成):
typescript
// packages/blog-server/src/config/logger.ts
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console()
]
})
查看日志:
- Render Dashboard → "Logs"
- 可以搜索、过滤、导出
14. 持续部署(CI/CD)
14.1 GitHub 集成
Vercel 自动部署:
- ✅ Push 到
main分支 → 自动部署到生产环境 - ✅ Pull Request → 自动部署预览环境
- ✅ 每次部署生成唯一 URL
Render 自动部署:
- ✅ Push 到
main分支 → 自动部署 - ✅ 构建日志实时查看
- ✅ 失败自动回滚到上一版本
14.2 分支策略
推荐工作流:
erlang
main (生产环境)
↑
└── develop (开发环境)
↑
└── feature/* (功能分支)
Vercel 多环境配置:
-
生产环境(main 分支)
- 自动部署到
blog-frontend.vercel.app
- 自动部署到
-
预览环境(Pull Request)
- 每个 PR 生成预览 URL
- 例如:
blog-frontend-git-feature-xxxx.vercel.app
14.3 版本回滚
Vercel 回滚:
- 进入项目 → "Deployments"
- 找到之前的成功部署
- 点击 "..." → "Promote to Production"
Render 回滚:
- 进入服务 → "Deploys"
- 找到之前的成功部署
- 点击 "..." → "Redeploy"
14.4 部署通知
Vercel 集成:
- 项目 Settings → "Git" → "Deploy Hooks"
- 添加 Webhook URL(例如:Slack、Discord)
- 每次部署自动通知
Render 集成:
- 服务 Settings → "Notifications"
- 添加邮箱或 Webhook
- 部署成功/失败自动通知
15. 总结
15.1 部署清单
完成以下所有步骤,你的全栈博客就成功部署了:
- 创建 Render PostgreSQL 数据库
- 部署后端到 Render
- 配置环境变量
- 初始化数据库
- 部署前端到 Vercel
- 部署后台到 Vercel
- 更新 CORS 配置
- 验证所有功能
15.2 最终架构
scss
用户 → Vercel (前端/后台) → Render (API) → Render (PostgreSQL)
↓ 静态资源 ↓ 业务逻辑 ↓ 数据存储
免费 100GB 免费 750h 免费 256MB
15.3 访问地址
| 服务 | URL |
|---|---|
| 前端 | https://blog-frontend-xxxx.vercel.app |
| 后台 | https://blog-admin-xxxx.vercel.app |
| API | https://blog-server-xxxx.onrender.com |
15.4 下一步
- 🎨 自定义域名(Vercel 和 Render 都支持)
- 📊 配置 Analytics 和监控
- 🔄 设置 UptimeRobot 防止休眠
- 💾 定期备份数据库
- 🚀 优化图片加载和缓存
- 📝 创建第一篇文章
16. 参考链接
- Vercel 文档 :vercel.com/docs
- Render 文档 :render.com/docs
- Nx Monorepo :nx.dev
- PostgreSQL 文档 :www.postgresql.org/docs/
- UptimeRobot :uptimerobot.com
🎉 恭喜!你的全栈博客已成功部署!
如果遇到问题,请参考 常见问题排查 章节,或查看项目根目录的其他文档:
- README.md - 本地开发指南
- RENDER_DEPLOYMENT.md - Render 详细部署指南
- CLAUDE.md - 完整项目文档