直接部署gin前后端分离项目需后端api独立暴露、前端由nginx/cdn托管;禁用gin静态服务,须配nginx history fallback、反向代理/api同域、systemd守护进程,并严格匹配前端base与nginx路径。

直接部署 Gin 前后端分离项目,核心就两点:后端 API 独立暴露,前端静态资源由 Nginx(或 CDN)托管,二者域名/端口分离,不混在一起。别用 router.StaticFS 或 LoadHTMLFiles 把前端塞进 Gin 里——那不是分离,是“假装分离”。
为什么不能用 Gin serve 前端静态文件
常见错误是把 dist 目录丢进 Gin,然后写:
r.Static("/static", "./dist/static")
r.LoadHTMLFiles("./dist/index.html")
这会导致几个实际问题:
- 前端路由(如 Vue Router 的
/dashboard)在刷新时 404,因为 Gin 没配 history fallback - Gin 的 HTTP server 不适合高并发静态资源分发,CPU 和内存浪费明显
- 无法利用 Nginx 的 gzip、缓存头、HTTP/2、SSL 终止等生产级能力
- 前端构建产物(
index.html)里的相对路径(./js/app.js)容易因 Gin 路由前缀错乱
Nginx 配置必须加 history fallback
Vue/React 路由是前端路由,Nginx 默认只认真实文件。用户直接访问 https://app.com/tasks 时,Nginx 会去找 /tasks 这个文件——当然不存在。解决办法是在 location / 块里加回退规则:
location / {
try_files $uri $uri/ /index.html;
}
注意这行必须放在 location /api(或类似后端代理规则)之后,否则所有请求都会被 fallback 到 index.html,连 /api/login 都被前端截获。
典型完整片段:
location /api {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /var/www/my-app/dist;
try_files $uri $uri/ /index.html;
}
Gin 后端必须允许跨域或与前端同源
前后端分离下,前端跑在 https://app.com,Gin 默认只响应同源请求。两种解法选其一:
- 开发期:用
github.com/gin-contrib/cors中间件放开跨域,比如cors.Default()(仅限测试) - 生产期:让前端和后端共用域名,用 Nginx 反向代理把
/api转发给 Gin,这样浏览器眼里全是同源请求,根本不需要 CORS
后者更安全、更符合生产规范。别在生产环境开 Access-Control-Allow-Origin: *,尤其当接口带 Cookie 或 JWT 时,必须指定明确域名,并设 credentials: true。
部署时 Gin 进程要后台常驻且自动重启
Gin 编译出的二进制文件本身不带守护能力。直接 ./server 启动,SSH 断开就挂了。推荐方式:
- 用
systemd(Linux 主流)写 service 文件,设Restart=always,日志走 journalctl - 避免用
nohup+&,没进程管理、没日志轮转、升级难 - 不要用
screen或tmux手动维持——适合调试,不适合上线
关键 systemd 示例(/etc/systemd/system/todo-api.service):
[Unit] Description=Todo API Server After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/todo/backend ExecStart=/opt/todo/backend/server -c /opt/todo/backend/config.yaml Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
然后 systemctl daemon-reload && systemctl enable todo-api && systemctl start todo-api。
真正容易被忽略的是:前端构建时的 base 配置(Vue 的 vite.config.ts 里 base,或 Vue CLI 的 publicPath)必须和 Nginx 的 root 或 alias 路径严格一致;否则 JS/CSS 路径 404,页面白屏但控制台没报错——这种问题查起来最耗时间。











