添加Railway部署配置文件和CORS设置

This commit is contained in:
patdelphi
2025-08-19 15:30:13 +08:00
parent 57cd405e94
commit 78f39e500b
11 changed files with 52 additions and 226 deletions

8
.gitignore vendored
View File

@@ -47,4 +47,10 @@ temp/
*.ntvs* *.ntvs*
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
# Database files (SQLite)
*.db
*.db-shm
*.db-wal
numerology.db*

1
Procfile Normal file
View File

@@ -0,0 +1 @@
web: npm start

View File

@@ -1,152 +0,0 @@
# Vercel 部署指南
本指南将帮助您将三算命项目部署到 Vercel 平台。
## 🚀 快速部署
### 1. 准备工作
确保您的项目已推送到 GitHub
```bash
git add .
git commit -m "准备Vercel部署"
git push origin master
```
### 2. 连接 Vercel
1. 访问 [vercel.com](https://vercel.com)
2. 使用 GitHub 账号登录
3. 点击 "New Project"
4. 选择您的 `suanming` 仓库
5. 点击 "Import"
### 3. 配置环境变量
在 Vercel 项目设置中添加以下环境变量:
```
NODE_ENV=production
JWT_SECRET=your_secure_jwt_secret_here
CORS_ORIGIN=https://your-app-name.vercel.app
```
**生成 JWT Secret**
```bash
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
```
### 4. 数据库配置
由于 Vercel 不支持 SQLite 文件存储,您需要迁移到云数据库:
#### 选项 1: Vercel Postgres推荐
1. 在 Vercel 项目中添加 Postgres 数据库
2. 复制连接字符串到环境变量 `DATABASE_URL`
3. 修改数据库连接代码
#### 选项 2: PlanetScale
1. 注册 [PlanetScale](https://planetscale.com)
2. 创建数据库
3. 获取连接字符串
4. 添加到环境变量 `DATABASE_URL`
### 5. 部署
配置完成后Vercel 会自动部署您的应用。
## 📁 项目结构说明
```
├── vercel.json # Vercel 配置文件
├── .env.production # 生产环境变量模板
├── src/ # 前端代码
└── server/ # 后端 API
```
## 🔧 配置文件说明
### vercel.json
- 配置构建和路由规则
-`/api/*` 路由到后端服务
- 其他路由指向前端应用
### 环境变量
- `NODE_ENV`: 设置为 production
- `JWT_SECRET`: JWT 令牌密钥
- `CORS_ORIGIN`: 允许的跨域来源
- `DATABASE_URL`: 数据库连接字符串(如使用云数据库)
## 🗄️ 数据库迁移
如果您选择使用云数据库,需要执行以下步骤:
### 1. 修改数据库连接
编辑 `server/database/index.cjs`
```javascript
// 替换 SQLite 连接为 PostgreSQL
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
});
```
### 2. 更新 SQL 语法
将 SQLite 语法转换为 PostgreSQL 语法:
- `INTEGER PRIMARY KEY AUTOINCREMENT``SERIAL PRIMARY KEY`
- `TEXT``VARCHAR``TEXT`
- 日期时间处理差异
### 3. 运行迁移
在 Vercel 部署后,通过 API 端点初始化数据库:
```
POST https://your-app.vercel.app/api/init-database
```
## 🚨 常见问题
### 1. 构建失败
- 检查 `package.json` 中的 `vercel-build` 脚本
- 确保所有依赖都在 `dependencies`
### 2. API 路由不工作
- 检查 `vercel.json` 路由配置
- 确保后端文件路径正确
### 3. 数据库连接错误
- 验证环境变量设置
- 检查数据库连接字符串格式
### 4. CORS 错误
- 设置正确的 `CORS_ORIGIN` 环境变量
- 检查后端 CORS 配置
## 📊 性能优化
1. **启用缓存**:配置适当的缓存头
2. **压缩资源**Vercel 自动启用 gzip
3. **CDN 加速**:静态资源自动通过 CDN 分发
4. **函数优化**:保持 API 函数轻量级
## 🔄 持续部署
Vercel 会自动监听 GitHub 仓库变化:
- 推送到 `master` 分支触发生产部署
- 推送到其他分支创建预览部署
## 📞 获取帮助
如果遇到问题:
1. 查看 Vercel 部署日志
2. 检查浏览器控制台错误
3. 参考 [Vercel 文档](https://vercel.com/docs)
---
部署完成后,您的应用将在 `https://your-app-name.vercel.app` 可用!

View File

@@ -1,5 +0,0 @@
// Vercel API 入口文件
const app = require('../server/index.cjs');
// 导出为 Vercel 函数
module.exports = app;

Binary file not shown.

Binary file not shown.

View File

@@ -8,7 +8,6 @@
"server": "nodemon server/index.cjs", "server": "nodemon server/index.cjs",
"build": "tsc -b && vite build", "build": "tsc -b && vite build",
"build:prod": "tsc -b && BUILD_MODE=prod vite build", "build:prod": "tsc -b && BUILD_MODE=prod vite build",
"vercel-build": "npm run build",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview", "preview": "vite preview",
"start": "node server/index.cjs", "start": "node server/index.cjs",

13
railway.json Normal file
View File

@@ -0,0 +1,13 @@
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "NIXPACKS"
},
"deploy": {
"startCommand": "npm start",
"healthcheckPath": "/health",
"healthcheckTimeout": 100,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 10
}
}

View File

@@ -42,7 +42,12 @@ app.use(helmet({
// CORS配置 // CORS配置
app.use(cors({ app.use(cors({
origin: process.env.NODE_ENV === 'production' origin: process.env.NODE_ENV === 'production'
? ['http://localhost:5173', 'http://localhost:4173'] // 生产环境允许的域名 ? [
'http://localhost:5173',
'http://localhost:4173',
/\.railway\.app$/, // Railway域名
/\.up\.railway\.app$/ // Railway新域名格式
]
: true, // 开发环境允许所有域名 : true, // 开发环境允许所有域名
credentials: true, credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
@@ -92,36 +97,31 @@ app.use('*', (req, res) => {
// 错误处理中间件 // 错误处理中间件
app.use(errorHandler); app.use(errorHandler);
// 启动服务器仅在非Vercel环境 // 启动服务器
if (process.env.VERCEL !== '1') { const server = app.listen(PORT, () => {
const server = app.listen(PORT, () => { console.log(`🚀 服务器运行在 http://localhost:${PORT}`);
console.log(`🚀 服务器运行在 http://localhost:${PORT}`); console.log(`📊 数据库文件: ${path.resolve('./numerology.db')}`);
console.log(`📊 数据库文件: ${path.resolve('./numerology.db')}`);
console.log(`🌍 环境: ${process.env.NODE_ENV || 'development'}`);
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到SIGTERM信号开始优雅关闭...');
server.close(() => {
console.log('HTTP服务器已关闭');
dbManager.close();
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('收到SIGINT信号开始优雅关闭...');
server.close(() => {
console.log('HTTP服务器已关闭');
dbManager.close();
process.exit(0);
});
});
} else {
console.log('🚀 Vercel serverless 环境已就绪');
console.log(`🌍 环境: ${process.env.NODE_ENV || 'development'}`); console.log(`🌍 环境: ${process.env.NODE_ENV || 'development'}`);
} });
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到SIGTERM信号开始优雅关闭...');
server.close(() => {
console.log('HTTP服务器已关闭');
dbManager.close();
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('收到SIGINT信号开始优雅关闭...');
server.close(() => {
console.log('HTTP服务器已关闭');
dbManager.close();
process.exit(0);
});
});
// 未捕获异常处理 // 未捕获异常处理
process.on('uncaughtException', (error) => { process.on('uncaughtException', (error) => {

View File

@@ -1,8 +1,7 @@
// 本地API客户端 // 本地API客户端
// 替代Supabase客户端提供相同的接口 // 替代Supabase客户端提供相同的接口
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3001/api';
(import.meta.env.PROD ? '/api' : 'http://localhost:3001/api');
interface ApiResponse<T> { interface ApiResponse<T> {
data?: T; data?: T;

View File

@@ -1,35 +0,0 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": {
"distDir": "dist"
}
},
{
"src": "api/index.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/api/(.*)",
"dest": "/api/index.js"
},
{
"src": "/(.*)",
"dest": "/index.html"
}
],
"env": {
"NODE_ENV": "production",
"VERCEL": "1"
},
"functions": {
"api/index.js": {
"maxDuration": 30
}
}
}