From 78f39e500b8ac07f3d909f863ed18beb29cc4c31 Mon Sep 17 00:00:00 2001 From: patdelphi Date: Tue, 19 Aug 2025 15:30:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Railway=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E5=92=8CCORS=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 8 ++- Procfile | 1 + VERCEL_DEPLOYMENT.md | 152 ------------------------------------------- api/index.js | 5 -- numerology.db-shm | Bin 32768 -> 32768 bytes numerology.db-wal | Bin 943512 -> 1075352 bytes package.json | 1 - railway.json | 13 ++++ server/index.cjs | 60 ++++++++--------- src/lib/localApi.ts | 3 +- vercel.json | 35 ---------- 11 files changed, 52 insertions(+), 226 deletions(-) create mode 100644 Procfile delete mode 100644 VERCEL_DEPLOYMENT.md delete mode 100644 api/index.js create mode 100644 railway.json delete mode 100644 vercel.json diff --git a/.gitignore b/.gitignore index 6b621b6..8512bf0 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,10 @@ temp/ *.ntvs* *.njsproj *.sln -*.sw? \ No newline at end of file +*.sw? + +# Database files (SQLite) +*.db +*.db-shm +*.db-wal +numerology.db* \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..e8f79ea --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: npm start \ No newline at end of file diff --git a/VERCEL_DEPLOYMENT.md b/VERCEL_DEPLOYMENT.md deleted file mode 100644 index 04506d7..0000000 --- a/VERCEL_DEPLOYMENT.md +++ /dev/null @@ -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` 可用! \ No newline at end of file diff --git a/api/index.js b/api/index.js deleted file mode 100644 index 24414e5..0000000 --- a/api/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// Vercel API 入口文件 -const app = require('../server/index.cjs'); - -// 导出为 Vercel 函数 -module.exports = app; \ No newline at end of file diff --git a/numerology.db-shm b/numerology.db-shm index 7ed1269a86bde844a1a811c5128100479d8f91d6..77a5f661e2dbe6e179568a9dab2465a028b0d50a 100644 GIT binary patch delta 423 zcmZo@U}|V!s+V}A%K!t63=9ISKw=R)14F-1(egUutw*-afA>0Ihj(D7^nzBi9oMFj zsvc%G$lU)(04mPL0Fq#sJdsg&7Zb z8jPDgT(2-PF@rdNn3z}~f|Fgm@31~+_{{JJsPr=vD@1g$lOHqVFQCZA$zKBXSYI%F zVfYKwCeF0kF60&?+Z%=-42&R^a*Ug8!tb%MzGV2y@DHqDvRT3-)>jPQ82$rwJ8w=% z+{VQAn&CSG10#^{v^g&22Or~4pvsGkn>9*x7#ZI}*lHC(_B)`Go11m2R9G3`1DWdq DNydZr delta 293 zcmZo@U}|V!s+V}A%K!t63=9HKft*F`3=ED*-q}B1Eppm6|K00=9o~V*3mv*0MD6a8 zsvc%G$lU)(04mPL0Fq#sJdsg&1{Ks}&<4AW-2kXwvEmI~u$ zoA7&VV6n+&36Fq^JT@mJZes#7;!=L_0i`Z6Zq_K(0VxNv)GBlsfs(g2>r|<*0vQ_s D!+vP~ diff --git a/numerology.db-wal b/numerology.db-wal index 96885538e4718772f23c2121d49866709c4e6d58..6ba263708921f86ff1f96c88c14467b10f2b33e1 100644 GIT binary patch delta 3617 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 diff --git a/package.json b/package.json index 47f1f15..133a92b 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "server": "nodemon server/index.cjs", "build": "tsc -b && vite build", "build:prod": "tsc -b && BUILD_MODE=prod vite build", - "vercel-build": "npm run build", "lint": "eslint .", "preview": "vite preview", "start": "node server/index.cjs", diff --git a/railway.json b/railway.json new file mode 100644 index 0000000..3fa6500 --- /dev/null +++ b/railway.json @@ -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 + } +} \ No newline at end of file diff --git a/server/index.cjs b/server/index.cjs index bbb6495..d2c738d 100644 --- a/server/index.cjs +++ b/server/index.cjs @@ -42,7 +42,12 @@ app.use(helmet({ // CORS配置 app.use(cors({ 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, // 开发环境允许所有域名 credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], @@ -92,36 +97,31 @@ app.use('*', (req, res) => { // 错误处理中间件 app.use(errorHandler); -// 启动服务器(仅在非Vercel环境) -if (process.env.VERCEL !== '1') { - const server = app.listen(PORT, () => { - console.log(`🚀 服务器运行在 http://localhost:${PORT}`); - 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 环境已就绪'); +// 启动服务器 +const server = app.listen(PORT, () => { + console.log(`🚀 服务器运行在 http://localhost:${PORT}`); + 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); + }); +}); // 未捕获异常处理 process.on('uncaughtException', (error) => { diff --git a/src/lib/localApi.ts b/src/lib/localApi.ts index bd560b9..2b5f62b 100644 --- a/src/lib/localApi.ts +++ b/src/lib/localApi.ts @@ -1,8 +1,7 @@ // 本地API客户端 // 替代Supabase客户端,提供相同的接口 -const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || - (import.meta.env.PROD ? '/api' : 'http://localhost:3001/api'); +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3001/api'; interface ApiResponse { data?: T; diff --git a/vercel.json b/vercel.json deleted file mode 100644 index ee9e322..0000000 --- a/vercel.json +++ /dev/null @@ -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 - } - } -} \ No newline at end of file