Vercel + Render 全栈博客部署实战指南

从零到部署:使用 Vercel 部署前端、Render 部署后端的完整实操手册 ,其中用到的实例皆是本人个人项目实战demo,部署后前端地址


📋 目录

  1. 部署架构概览
  2. 前置准备
  3. [第一步:部署后端到 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")
  4. 第二步:初始化数据库
  5. [第三步:部署前端到 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")
  6. [第四步:部署后台管理到 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")
  7. 第五步:连接前后端
  8. 第六步:验证部署
  9. [Monorepo 特殊配置说明](#Monorepo 特殊配置说明 "#9-monorepo-%E7%89%B9%E6%AE%8A%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E")
  10. 环境变量完整清单
  11. 免费额度说明
  12. 常见问题排查
  13. 优化建议
  14. 持续部署(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:

  1. 后端 → Render (获取 API URL)
  2. 数据库初始化 → Render Shell
  3. 前端 → Vercel (配置 API 代理)
  4. 后台 → Vercel (配置 API 代理)
  5. 连接测试 → 更新 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 注册

  1. 访问 render.com
  2. 点击 "Get Started" → "Sign Up with GitHub"
  3. 授权 Render 访问你的 GitHub 仓库
  4. ✅ 无需信用卡,完全免费

Vercel 注册

  1. 访问 vercel.com
  2. 点击 "Sign Up" → "Continue with GitHub"
  3. 授权 Vercel 访问你的 GitHub 仓库
  4. ✅ 无需信用卡,完全免费

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 数据库

  1. 登录 Render Dashboard

  2. 点击右上角 "New +" → 选择 "PostgreSQL"

  3. 填写数据库配置:

    字段
    Name blog-postgres
    Database blog_system
    User blog_user(自动生成,可修改)
    Region 选择 Singapore(离中国最近)
    PostgreSQL Version 16(默认)
    Plan Free
  4. 点击 "Create Database"

  5. 等待约 1-2 分钟,状态变为 "Available"

  6. 保存连接信息(稍后需要):

    • 进入数据库 → "Info" 标签
    • 记录:
      • Hostname (例如:dpg-xxxx-a.singapore-postgres.render.com
      • Port (通常是 5432
      • Databaseblog_system
      • Usernameblog_user
      • Password(自动生成的长密码)

3.2 创建 Web Service(后端 API)

  1. 在 Render Dashboard,点击 "New +""Web Service"

  2. 点击 "Build and deploy from a Git repository""Next"

  3. 选择你的 GitHub 仓库 blog(如果没有显示,点击 "Configure account" 授权)

  4. 填写服务配置:

    字段 说明
    Name blog-server 服务名称
    Region Singapore 与数据库同区域
    Branch main Git 分支
    Root Directory packages/blog-server ⚠️ 重要:Monorepo 子目录
    Runtime Node 自动检测
    Build Command npm install && npm run build 安装依赖并编译 TypeScript
    Start Command npm start 启动服务
    Plan Free 免费计划
  5. 点击 "Advanced" 展开高级选项(暂不配置,稍后添加环境变量)

  6. 点击 "Create Web Service"

构建过程:约 3-5 分钟,在 "Logs" 标签查看进度

3.3 配置环境变量

构建完成后(状态显示 "Live" 或 "Deploy failed",先别管),配置环境变量:

  1. 在 Web Service 页面,点击 "Environment" 标签

  2. 点击 "Add Environment Variable",逐个添加以下变量:

基础配置

bash 复制代码
NODE_ENV=production

JWT 配置

bash 复制代码
JWT_SECRET=51de2d30c5629597bf6f41dbcf9f41beb714bb31e91adb5899d25fce64202fd9

💡 生产环境必须修改:使用以下命令生成新密钥:

bash 复制代码
node -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
  1. 点击 "Save Changes"

  2. Render 会自动触发重新部署(约 2 分钟)

3.4 查看部署日志

  1. 在 "Logs" 标签,确认看到以下内容:
dart 复制代码
🚀 Server is running on http://0.0.0.0:10000
📝 Environment: production
🗄️  Database: blog_system@dpg-xxxx.singapore-postgres.render.com:5432
  1. 如果看到错误,检查环境变量是否正确

3.5 获取 API URL

  1. 在 Web Service 顶部,复制服务 URL:

    arduino 复制代码
    https://blog-server-xxxx.onrender.com
  2. 保存这个 URL,稍后部署前端时需要

  3. 测试 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

  1. 在 Web Service 页面,点击 "Shell" 标签

  2. 点击 "Launch Shell" 按钮

  3. 等待 Shell 启动(约 10 秒)

  4. 在 Shell 中运行初始化脚本:

    bash 复制代码
    npm run db:init
  5. 成功后会看到:

    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 导入项目

  1. 登录 Vercel Dashboard

  2. 点击 "Add New..." → "Project"

  3. 选择你的 GitHub 仓库 blog

  4. 点击 "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 配置

  1. 在 "Build and Output Settings" 下找到 "Root Directory"
  2. 点击 "Edit" 按钮
  3. 选择 packages/blog-frontend

Build Command 配置

  1. 勾选 "Override" 复选框
  2. 输入完整的 Monorepo 构建命令

5.3 配置 API 重写(重要)

⚠️ Vercel 项目配置会读取 vercel.json,但我们手动确认一下:

  1. 在部署前,确认项目根目录的 packages/blog-frontend/vercel.json 包含:
json 复制代码
{
  "rewrites": [
    {
      "source": "/api/:path*",
      "destination": "https://blog-server-xxxx.onrender.com/api/:path*"
    },
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}
  1. ⚠️ 重要 :将 https://blog-server-xxxx.onrender.com 替换为你在步骤 3.5 获取的实际 Render URL

  2. 如果已修改,提交代码:

bash 复制代码
git add packages/blog-frontend/vercel.json
git commit -m "fix: update API URL in vercel.json"
git push origin main

5.4 部署

  1. 配置完成后,点击 "Deploy"

  2. ⏳ 构建时间:约 2-3 分钟

  3. 成功后会显示:

    复制代码
    ✅ Deployment Ready
  4. 点击 "Visit" 或复制部署 URL(例如:https://blog-frontend-xxxx.vercel.app

  5. 保存前端 URL,稍后需要更新 Render 的 CORS 配置

5.5 验证前端部署

访问前端 URL,应该看到:

  • ✅ 博客首页加载正常
  • ✅ 分类列表显示(从 Render API 获取)
  • ⚠️ 可能显示 "暂无文章"(正常,因为还没创建文章)

6. 第四步:部署后台管理到 Vercel

6.1 部署流程

与前端类似,重复步骤 5,但使用不同的配置:

  1. 在 Vercel Dashboard,点击 "Add New..." → "Project"

  2. 再次选择 blog 仓库

  3. Vercel 会提示 "This repository is already connected",选择 "Import Anyway"

  4. 配置项目:

字段
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
  1. 确认 packages/blog-admin/vercel.json 中的 API URL 与前端一致

  2. 点击 "Deploy"

  3. 获取后台 URL(例如:https://blog-admin-xxxx.vercel.app

6.2 验证后台部署

访问后台 URL,应该看到:

  • ✅ 登录页面加载正常
  • ⚠️ 先不要登录(CORS 还未配置)

7. 第五步:连接前后端

7.1 更新 Render 的 CORS 配置

现在我们有了前端和后台的 URL,需要更新 Render 环境变量:

  1. 回到 Render Dashboard → blog-server 服务

  2. 进入 "Environment" 标签

  3. 更新以下变量:

    bash 复制代码
    FRONTEND_URL=https://blog-frontend-xxxx.vercel.app
    bash 复制代码
    ADMIN_URL=https://blog-admin-xxxx.vercel.app

    替换为你实际的 Vercel URL

  4. 点击 "Save Changes"

  5. Render 会自动重启服务(约 1 分钟)

7.2 测试 API 连接

  1. 打开浏览器控制台(F12)

  2. 访问前端 URL:https://blog-frontend-xxxx.vercel.app

  3. 在 Network 标签查看 API 请求:

    • ✅ 应该看到 /api/categories 请求成功
    • ✅ 响应头包含 Access-Control-Allow-Origin
  4. 如果看到 CORS 错误,检查:

    • Render 环境变量是否正确
    • 服务是否已重启
    • URL 是否包含 https://

7.3 验证登录功能

  1. 访问后台 URL:https://blog-admin-xxxx.vercel.app

  2. 使用默认账号登录:

    • 用户名admin
    • 密码admin123
  3. 登录成功后,应该进入 Dashboard

  4. 查看:

    • ✅ 分类列表显示
    • ✅ 文章列表为空(正常)
    • ✅ 可以创建新文章

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 测试后台登录

  1. 打开浏览器控制台

  2. 访问 https://blog-admin-xxxx.vercel.app

  3. 输入账号密码,点击登录

  4. 在 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 测试图片上传

  1. 登录后台管理

  2. 进入 "文章管理" → "创建文章"

  3. 点击上传封面图片

  4. 选择一张图片(<5MB)

  5. 确认:

    • ✅ 上传成功
    • ✅ 图片预览显示
    • ✅ 发布文章后,前端可以看到图片

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

分解

  1. npm install - 安装根依赖(Nx, TypeScript 等)
  2. cd packages/blog-frontend - 进入前端目录
  3. 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*"
    }
  ]
}

工作原理

  1. 前端发起请求:/api/articles
  2. Vercel 拦截请求,重写为:https://blog-2eqo.onrender.com/api/articles
  3. 转发到 Render 后端
  4. 返回响应给前端

优点

  • ✅ 前端无需关心 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.jsonrewrites,前端可以直接用 /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(推荐)

  1. 注册 uptimerobot.com(免费)
  2. 添加 Monitor:
    • Monitor Type: HTTP(s)
    • URL : https://blog-server-xxxx.onrender.com/api/health
    • Monitoring Interval: 5 分钟
  3. UptimeRobot 会每 5 分钟 ping 一次,保持服务唤醒

方法 2:使用 Cron-job.org

  1. 注册 cron-job.org
  2. 创建定时任务:
    • URL : https://blog-server-xxxx.onrender.com/api/health
    • Execution: 每 10 分钟

方法 3:前端定时请求(不推荐)

在前端添加定时器:

javascript 复制代码
// 不推荐:消耗用户带宽
setInterval(() => {
  fetch('/api/health')
}, 5 * 60 * 1000) // 每 5 分钟

12. 常见问题排查

12.1 API 502/504 错误

症状:前端显示 "网络错误" 或 "502 Bad Gateway"

原因:Render 服务休眠,正在唤醒

解决方案

  1. 等待 30-50 秒,刷新页面

  2. 如果仍然失败,检查 Render 服务状态:

    • 进入 Render Dashboard → blog-server
    • 查看 "Logs" 是否有错误
    • 确认服务状态为 "Live"
  3. 如果服务启动失败,检查:

    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_URLADMIN_URL 不正确

解决方案

  1. 检查 Render 环境变量:

    • FRONTEND_URL 必须与 Vercel 前端 URL 完全一致
    • 包含 https://
    • 不包含尾部斜杠 /
  2. 确认 CORS 配置(packages/blog-server/src/middleware/cors.ts):

    typescript 复制代码
    origin: [
      env.FRONTEND_URL,  // 前端 URL
      env.ADMIN_URL      // 后台 URL
    ]
  3. 重启 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

原因:数据库环境变量配置错误

解决方案

  1. 检查 Render 环境变量:

    • DB_HOSTDB_PORTDB_USERDB_PASSWORDDB_NAME
    • 与数据库 "Info" 标签的信息一致
  2. 确认数据库状态为 "Available"

  3. 测试连接(在 Render Shell):

    bash 复制代码
    psql $DATABASE_URL -c "SELECT 1"

12.5 图片显示 404

症状:前端文章列表或详情页,封面图片显示 404

原因:数据库未初始化,或图片未上传

解决方案

  1. 确认数据库已初始化:

    bash 复制代码
    # 在 Render Shell
    psql $DATABASE_URL -c "SELECT COUNT(*) FROM images"
  2. 如果表不存在,运行:

    bash 复制代码
    npm run db:init
  3. 上传测试图片:

    • 登录后台管理
    • 创建文章并上传封面

12.6 登录失败

症状:输入账号密码后,提示 "用户名或密码错误"

原因:管理员账号未创建

解决方案

  1. 检查数据库中的管理员:

    bash 复制代码
    # 在 Render Shell
    psql $DATABASE_URL -c "SELECT username, email FROM admin_users"
  2. 如果为空,重新初始化:

    bash 复制代码
    npm run db:init
  3. 或手动创建管理员:

    bash 复制代码
    npm run create-admin

13. 优化建议

13.1 防止 Render 休眠

使用 UptimeRobot 定期 ping API(推荐):

  1. 注册 uptimerobot.com
  2. 添加 HTTP Monitor
  3. URL: https://blog-server-xxxx.onrender.com/api/health
  4. 间隔: 5 分钟

效果

  • ✅ 服务始终保持活跃
  • ✅ 用户访问无需等待唤醒
  • ✅ 免费,无需额外成本

13.2 图片优化

问题:图片存储在数据库中,占用空间且加载慢

优化方案

  1. 压缩图片(前端上传前)

    • 使用 browser-image-compression
    • 限制宽度 1200px,质量 80%
  2. 迁移到对象存储(推荐)

    • 使用 Cloudflare R2(免费 10GB)
    • 或 AWS S3 + CloudFront
    • 数据库只存储 URL
  3. 添加图片缓存

    • Vercel 自动缓存静态资源
    • 后端添加 Cache-Control

13.3 性能监控

Vercel Analytics(免费)

  1. 进入 Vercel 项目 → "Analytics"
  2. 启用 Web Analytics
  3. 查看:
    • 页面加载时间
    • 用户访问量
    • 地理分布

Render Metrics(免费)

  1. 进入 Render 服务 → "Metrics"
  2. 查看:
    • 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 多环境配置

  1. 生产环境(main 分支)

    • 自动部署到 blog-frontend.vercel.app
  2. 预览环境(Pull Request)

    • 每个 PR 生成预览 URL
    • 例如:blog-frontend-git-feature-xxxx.vercel.app

14.3 版本回滚

Vercel 回滚

  1. 进入项目 → "Deployments"
  2. 找到之前的成功部署
  3. 点击 "..." → "Promote to Production"

Render 回滚

  1. 进入服务 → "Deploys"
  2. 找到之前的成功部署
  3. 点击 "..." → "Redeploy"

14.4 部署通知

Vercel 集成

  1. 项目 Settings → "Git""Deploy Hooks"
  2. 添加 Webhook URL(例如:Slack、Discord)
  3. 每次部署自动通知

Render 集成

  1. 服务 Settings → "Notifications"
  2. 添加邮箱或 Webhook
  3. 部署成功/失败自动通知

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. 参考链接


🎉 恭喜!你的全栈博客已成功部署!

如果遇到问题,请参考 常见问题排查 章节,或查看项目根目录的其他文档:

相关推荐
写代码的皮筏艇1 小时前
React中的'插槽'
前端·javascript
韩曙亮1 小时前
【Web APIs】元素可视区 client 系列属性 ② ( 立即执行函数 )
前端·javascript·dom·client·web apis·立即执行函数·元素可视区
秋邱1 小时前
AR 技术创新与商业化新方向:AI+AR 融合,抢占 2025 高潜力赛道
前端·人工智能·后端·python·html·restful
www_stdio1 小时前
JavaScript 原型继承与函数调用机制详解
前端·javascript·面试
羽沢311 小时前
vue3 + element-plus 表单校验
前端·javascript·vue.js
前端九哥2 小时前
如何让AI设计出Apple风格的顶级UI?
前端·人工智能
红石榴花生油2 小时前
Linux服务器权限与安全核心笔记
java·linux·前端
之恒君2 小时前
事件冒泡和事件捕获详解
前端·javascript
只与明月听2 小时前
一个有趣的面试题
前端·后端·python