在免费基础设施上部署全栈应用
我们为 G3HUB 构建了一个学习管理系统。 技术栈:React 18、Node.js 20 和 PostgreSQL 15。
我们没有 VPS。 我们没有云服务预算。 我们只有一个 cPanel 共享主机账号和一个截止日期。
大多数教程都假设你拥有专用服务器。我们必须找到一种方法,让不同的服务以每月 0 美元的成本进行通信。
架构
• 前端:React + Vite(托管在 cPanel 上) • 后端:Node.js + Express(托管在 Render 免费层) • 数据库:PostgreSQL(托管在 Supabase 免费层)
障碍与解决方案
1. 共享主机拦截数据库连接 我们尝试在 cPanel 上运行 Node.js API。但失败了,因为主机拦截了指向 PostgreSQL 5432 端口的出站连接。 解决方案:将 API 迁移到 Render。Render 允许这些连接。
2. Monorepo 部署错误
Render 无法识别我们的 pnpm workspace 依赖项,例如 @workspace/db。
解决方案:我们使用 esbuild 将所有内容打包成一个 6.4MB 的单一文件。然后,我们使用一个仅包含外部依赖项的极简 package.json。这使得 API 变得自包含。
3. CORS 和代理问题
共享主机上的 Apache mod_proxy 受到限制。我们无法轻松地将前端的 API 调用转发到 Render。
解决方案:我们使用了一个 PHP cURL 代理。
前端调用本地 PHP 脚本,PHP 脚本再将请求转发到 Render。这绕过了 CORS 问题和防火墙限制。
4. SSL 证书错误
Supabase 连接池导致 Node.js 出现 SSL 错误。
解决方案:我们设置了环境变量 NODE_TLS_REJECT_UNAUTHORIZED=0。
费用明细
• cPanel: $0 (现有) • Render: $0 (免费层) • Supabase: $0 (免费层) • 总计:$0/月
给工程师的启示
- 及早测试出站连通性。在编写代码之前,先检查你的服务器是否真的能与数据库通信。
- 在 Monorepo 中使用 esbuild。单个打包文件比复杂的文件夹结构更容易部署。
- 使用 UptimeRobot。Render 的免费层在 15 分钟后会进入休眠状态。通过简单的 ping 操作可以保持其活跃。
- 避免在数据库密码中使用特殊字符。在连接字符串中使用
@或!会导致无休止的 URL 编码难题。
如果负担得起,买一个 5 美元的 VPS。它能消除所有这些障碍。但如果你只有 0 美元,通过创造性的路由也能实现生产级应用。
来源:https://dev.to/oyohedmond/deploying-a-full-stack-lms-on-shared-hosting-render-free-the-hard-way-4ke0
可选学习社区:https://t.me/GyaanSetuAi
