CWF 项目部署复盘总结 / CWF Project Deployment Retrospective
这次部署 CWF 前后端分离项目,遇到了很多不懂的问题,踩了不少坑,过程虽然曲折,但收获很多,现将所有收获和遇到的问题整理总结如下,方便后续复盘回顾:
1. TiDB 数据库连接地址相关
TiDB给我的那条链接,本质就是数据库的「完整地址 + 钥匙」,也就是项目中的 DATABASE_URL,它的组成是:
mysql://用户名:密码@主机:端口/库名?参数后端就是靠这一串信息,明确知道数据库在哪台机器上、用什么端口连接、用什么账号密码登录、连到哪个库。
| 环境 | DATABASE_URL 示例 |
|---|---|
| 本地开发 | mysql://root:密码@localhost:3306/你的库名 |
| 服务器 | mysql://root:密码@服务器IP:3306/你的库名 |
⚠️ 注意:
localhost:3000是后端自己的端口,跟数据库没有关系,数据库的默认端口一般是 3306,并不是 3000。
后端要想找到数据库,必须靠这个 URL,而且这个 URL 必须写在后端的 .env 文件里,Prisma 就是读取这个 DATABASE_URL 去连接数据库。
2. 本地 Prisma 连接 TiDB 失败,但腾讯云服务器连接成功的原因
核心原因
网络权限 + 地区防火墙把本地访问拦住了
为什么服务器能连上?
我的腾讯云服务器在北京,TiDB 在东京,两者都是云服务器,之间可以通过内网或高速公网互通:
- TiDB 后台默认允许云厂商 IP 访问
- 服务器 IP 干净、稳定
- 国外访问顺畅,没有家庭网络的 NAT、防火墙、运营商限制
所以在服务器上执行 prisma db push 就能直接连通。
为什么我本地连不上?
| 原因 | 说明 |
|---|---|
| 1. TiDB 开了「IP白名单」 | 绝大多数云数据库默认不允许任意公网IP乱连,只允许手动添加的IP访问。我本地的家庭网IP是动态的,根本没添加到白名单里,而服务器IP是固定的,可能被自动允许了。 |
| 2. 国内家庭网访问国外服务不稳定 | 我本地的电脑通过电信/移动网络访问东京TiDB,会经过防火墙,延迟高、易丢包、连接被重置、被限流,Prisma 连接一下就超时,直接失败;而腾讯云北京服务器到东京节点,走的是云厂商专线,非常稳定。 |
| 3. 本地防火墙/杀毒软件/路由器拦截 | 外出的 3306 这类数据库端口,很多家庭网默认会拦截,自己都不知道。 |
📌 结论(刻进脑子里,别死缠烂打)
本地连远程云数据库失败 ≠ 项目坏了,这是常态,不是异常。
真正部署时,本地只管写代码,数据库同步、连接测试,都在服务器上做。本地不用纠结,服务器能通就行。
精简总结:TiDB 不让我本地电脑连,但允许腾讯云服务器连,原因是白名单、跨国网络、家庭网限制,所以本地连不上正常,服务器能通才是真的通。
3. Mixed Content(混合内容)报错问题
刚开始没有给服务器IP上二级域名,前端是 Vercel 部署的,默认发 HTTPS 请求,后端是直接用服务器IP+端口,走 HTTP 协议,就出现了 Mixed Content 报错。
具体情况
- 前端:Vercel 部署,地址是
https://xxx.vercel.app或https://cw.tidenflow.life - 后端:腾讯云服务器 IP + 端口,比如
http://1.2.3.4:3000
这就出现了 HTTPS 页面往 HTTP 地址发请求的情况,浏览器直接判定为不安全,拦截请求,报 Mixed Content 错误。
浏览器为什么要拦?
规则非常死:
- HTTPS 页面 = 加密、安全
- HTTP 请求 = 不加密、不安全
- 浏览器不允许安全页面去调用不安全接口,怕被劫持、窃听
只要出现页面是
https://、接口是http://,就会直接报错,请求发不出去。
为什么后来用二级域名 + Nginx 就好了?
给后端弄了个域名:api.tidenflow.life,用 Nginx 配上了 SSL 证书,让后端接口变成了 https://api.tidenflow.life:
- 前端是 HTTPS ✅
- 后端也是 HTTPS ✅
- 协议一致,浏览器就不拦截了,请求就能正常连通
补充:Mixed Content 报错的核心诱因(关键踩坑点)
后续复盘发现,初期 Mixed Content 报错的核心原因,并非前端代码写死IP请求,而是Vercel 环境变量配置错误:前端代码中未写死任何IP请求,而是通过 VITE_API_BASE_URL 环境变量指向后端接口,但我在Vercel控制台配置该变量时,最初将其填写为 https://服务器IP 或 http://服务器IP,导致前端发起的请求出现两种致命问题:
- 若填写
https://服务器IP:IP本身是不会有SSL证书,浏览器无法识别该HTTPS地址,直接判定为不安全,无法建立连接;
HTTP 和 HTTPS 的真正区别只有一个:有没有加密。
HTTP:明文传输,裸奔,别人能窃听、篡改
HTTPS:加密传输,安全,别人看不懂
而实现加密的工具就是:SSL / TLS 证书
没有证书 → 不可能是 HTTPS。
域名 和 HTTPS 是什么关系?
证书必须绑定 “域名”,不能绑定 “单纯 IP”。
你想搞 HTTPS->就必须申请证书->申请证书必须填域名
IP 不能申请正规 SSL 证书
所以现实中:
HTTPS 一定需要域名,不能只靠 IP。
如果 IP 本身有 SSL 证书,前端是不是就能访问后端?
理论上:可以 /// 现实中:不可能- 若填写
http://服务器IP:前端Vercel为HTTPS协议,请求HTTP接口触发浏览器Mixed Content安全策略,请求在浏览器内部直接被拦截,从未到达后端服务器(后端、Nginx、防火墙均无相关请求日志)。
直至将Vercel环境变量 VITE_API_BASE_URL 修正为 https://api.taineflow.life(后端二级域名,已配置SSL和Nginx),前后端协议一致、地址合法,请求才正常放行,报错彻底解决。
✅ 关键结论:前端接口请求异常时,优先检查Vercel环境变量的协议和地址格式,避免直接填写服务器IP(无SSL证书),需填写已配置HTTPS的后端域名。
4. 域名、二级域名与 Nginx 反向代理
域名与二级域名
| 概念 | 说明 |
|---|---|
| 主域名(一级域名) | 我花钱买的、在域名服务商那里备案/管理的根域名。我的主域名是 taineflow.life |
| 二级域名 | 格式是 xxx.taineflow.life,如 cwf.taineflow.life(前端)、api.taineflow.life(后端) |
| 三级域名 | 格式是 xxx.xxx.taineflow.life,如 api.c.taineflow.life |
浏览器怎么识别?它有一套固定规则:
.com、.cn、.life这些叫 顶级域- 我买的
taineflow.life叫 主域名/一级域名 - 前面加一段就是 二级域名,再加一段就是 三级、四级……
本质就是:二级域名 = 主域名的"子房间",管理权完全在我手里,不需要再买,直接在 DNS 解析里加一条记录就行。
为什么要分二级域名?
不是技术必须,是工程上特别舒服:
- 前端一个域名、后端接口一个域名、博客一个域名、个人站一个域名
- 互不干扰,清爽、好维护、好排查
Nginx 反反向代理
关于 Nginx 反向代理,只需要记住这 3 句话:
1. 最核心作用:隐藏真实 IP + 统一入口
我后端本来是
http://123.123.123.123:3000,别人一抓就知道我服务器IP,能直接攻击、扫端口;用 Nginx 反向代理后,别人访问的是https://api.taineflow.life,看不到真实IP,这就是保护服务器IP。
2. 第二个作用:把"域名"转发到"端口"
外部访问 https://api.taineflow.life,Nginx 内部偷偷转发到 127.0.0.1:3000,用户完全无感。
具体来说:
- Node 后端是跑在
127.0.0.1:3000或者服务器内网IP:3000 - 它只认端口 3000,不认什么
api.taineflow.life - 域名这东西,Node 后端根本看不懂,后端只认识 IP + 端口
现实生活类比:
我后端住在 3000号房间,用户只知道我小区名字
api.taineflow.life,Nginx 就是小区保安+前台,用户喊"我找 api.taineflow.life!",保安(Nginx)说"好,他在3000房间,我帮你转过去",用户根本不用知道房间号,只需要知道小区名,这就是把域名转发到端口。
为什么要这么做?
- 后端不能直接暴露端口
- 一个服务器可以跑很多项目(3000、3001、3002…)
- 用不同域名区分,用户只记好记的域名,不用记复杂端口
3. 第三个作用:统一 HTTPS
我的 Node 服务一般只跑 HTTP,Nginx 负责装 SSL 证书、对外提供 HTTPS、对内还是 HTTP 访问我的后端,这样就解决了之前的 Mixed Content 问题。
💡 补充说明
我后来明白,即使不搞二级域名,除了 Mixed Content 报错,其他倒也无所谓,因为前后端直接用 IP 通信只是不安全,但功能上是能通的。
但必须加一个域名,才能进入加密范围,也就是 HTTPS:
| 方案 | 安全性 | 浏览器拦截 |
|---|---|---|
http://服务器IP:3000 | ❌ 裸奔 | ❌ 拦截 |
https://api.taineflow.life | ✅ 安全 | ✅ 不拦截 |
浏览器强制加了一道规矩:我的前端在 Vercel,是 HTTPS 加密环境,后端如果是 IP,就是 HTTP 明文,浏览器直接判定加密页面 ≠ 明文接口,不安全就拦截,报 Mixed Content。
所以必须给后端也搞成 HTTPS,而光有 IP 搞不了 HTTPS,必须要有域名,有域名才能申请 SSL 证书,有证书才能变成 HTTPS。
精简总结
- IP直连:能用,但裸奔、HTTP、浏览器拦
- 域名+Nginx:能上 HTTPS,安全、协议统一、不拦
我昨天所有折腾域名、反向代理,本质就是为了给后端也穿上 HTTPS 这件"安全外套"。
5. 域名解析配置
域名解析的四个核心要素:
| 要素 | 说明 |
|---|---|
| 主机记录 | 我要的二级/三级域名前缀 |
| 记录类型 | 我想让它指向 IP 还是另一个域名 |
| 线路类型 | 不用管,默认就行 |
| 记录值 | 指向的目标(IP或别人域名) |
我的主域名是
taineflow.life,所有域名解析的例子,都是 主机记录 + 主域名 拼起来就是最终域名。
具体例子
例子 1:A记录 → 指向服务器 IP
- 主机记录:
api - 记录类型:
A - 记录值:
123.123.123.123(我的腾讯云IP) - 拼接结果:
api.taineflow.life→ 指向123.123.123.123
例子 2:A记录,三级域名
- 主机记录:
api.c - 记录类型:
A - 记录值:
123.123.123.123 - 拼接结果:
api.c.taineflow.life→ 指向 IP,这就是三级域名
例子 3:CNAME → 指向另一个域名(Vercel 专用)
- 主机记录:
cw - 记录类型:
CNAME - 记录值:
cname.vercel-dns.com - 拼接结果:
cw.taineflow.life→ 指向cname.vercel-dns.com,Vercel 再内部帮我转到我的前端项目
例子 4:给主域名本身设置(@就是主域名)
- 主机记录:
@ - 记录类型:
A - 记录值:
1.2.3.4 - 拼接结果:
taineflow.life→ 指向1.2.3.4
例子 5:www 前缀
- 主机记录:
www - 记录类型:
A - 记录值:
1.2.3.4 - 拼接结果:
www.taineflow.life→ 指向 IP
超级精简口诀(记这个就够)
主机记录 = 前缀
最终域名 = 前缀.主域名
A = 指向 IP
CNAME = 指向别人域名
记录值 = 目标是谁
6. 服务器防火墙设置
后端本来是 HTTP → 浏览器拦(混合内容),我给后端套上二级域名 + Nginx + SSL → 后端变成 HTTPS 了,但这只是"饭店内部装修好了",大门没开:
防火墙没放行 443 端口,外面的车(HTTPS 请求)开到门口,进不来。
我在腾讯云防火墙开了这样的规则:
| 来源 | 协议 | 端口 | 策略 |
|---|---|---|---|
0.0.0.0/0 | TCP | 443 | 允许 |
这就等于把饭店大门打开,允许所有人进来吃饭。
一句话总结整个部署的逻辑链
前端 Vercel 是 HTTPS → 后端必须也 HTTPS(否则浏览器报 Mixed Content)→ 要 HTTPS 必须有域名 + SSL + Nginx → HTTPS 默认走 443 端口 → 服务器防火墙默认关 443 → 必须手动开放 443 → 开放后,请求才能进到 Nginx → Nginx 再转发给我后端 3000 端口,,一步都不能少。
昨天配置完 443 那一刻,才真正打通了。
7. 域名备案问题
核心规则
域名 → 指向中国大陆服务器 → 必须备案
不备案 → 域名会被运营商直接屏蔽 → 打不开
我昨晚遇到的诡异现象
| 访问方式 | 结果 |
|---|---|
| 直接访问服务器 IP | ✅ 能打开 |
访问 api.taineflow.life | ❌ 打不开 |
| ping 域名 | ✅ 能通 |
| 端口都开了、Nginx 配了、HTTPS 好了 | ✅ 一切正常 |
为什么会这样?
运营商只查「域名」,不查「IP」:
- 我用 IP 访问,运营商不管
- 我用域名访问,运营商检查 → 发现没备案 → 直接拉黑屏蔽
备案到底是什么?
大白话来说:
备案 = 给我的「域名+服务器」在工信部做实名制登记
相当于:
- 开饭店要营业执照
- 开车要车牌
- 开网站 + 国内服务器 = 必须备案
- 不备案 = 非法运营 → 直接屏蔽
为什么这么恶心?为什么本地测试不出来?
| 原因 | 说明 |
|---|---|
| 备案是大陆特有的规定 | 海外服务器(香港、新加坡、日本、美国)不需要备案 |
| 本地测试、IP访问都正常 | 但一上域名 + 国内服务器 → 立刻触发屏蔽 |
我chao昨晚排查了两个半小时,不是技术问题,是备案问题。
📝 总结
部署过程中踩坑是成长的必经之路,以下是关键要点:
- 数据库连接:本地连不上≠项目坏了,服务器能通才是真的通
- HTTPS 必要性:前端 HTTPS,后端必须也是 HTTPS,否则浏览器拦截
- 域名 + Nginx:不仅安全,还能隐藏真实 IP、简化访问
- 域名备案:国内服务器 + 域名 = 必须备案,否则被屏蔽
- 防火墙:HTTPS 默认 443 端口,记得开放