芋道项目部署时,前端和门户网站如何通过 Nginx 转发后台接口,而不直接暴露后端地址

在部署芋道项目时,很多人一开始都会直接让前端去请求后端地址,比如:

text 复制代码
http://后端域名/admin-api

或者打包后前端里还残留着:

text 复制代码
http://localhost:48082

这样会带来几个常见问题:

  • 后端地址直接暴露给用户
  • 容易出现跨域问题
  • 前端打包后接口还是请求 localhost
  • 页面刷新后 404
  • 更换后端地址时,还要重新改前端代码

更推荐的做法是:

  • 前端页面访问自己的域名
  • 前端请求接口时,也走自己的域名
  • 由 Nginx 再把接口请求转发到真正的后端服务

这篇文章把这个问题完整讲清楚,包括:

  1. 为什么不能直接写 localhost
  2. 为什么推荐前端走同域名请求
  3. 芋道管理后台前端配置怎么写
  4. 门户网站前端配置怎么写
  5. Nginx 怎么转发
  6. 页面刷新 404 怎么解决
  7. 常见报错怎么排查

一、问题现象

很多人部署完前端后,打开页面会发现:

  • 登录验证码请求失败
  • 接口请求地址还是 localhost
  • 浏览器控制台报错
  • 页面一刷新就 404
  • 明明后端在服务器上运行,前端却请求不到

例如浏览器里出现这样的请求地址:

text 复制代码
http://localhost:48082/admin-api/system/captcha/get

这就是典型问题。

这里一定要明白:

前端页面是在用户浏览器里运行的。

当前端去请求 localhost:48082 时,请求的不是你的服务器,而是用户自己电脑的 localhost

所以用户当然访问不到你服务器上的后端。


二、正确思路:前端请求自己的域名,Nginx 再转发到后端

正确做法不是让前端直接写后端地址,而是这样:

假设:

  • 管理后台前端域名:admin.example.com
  • 门户网站前端域名:www.example.com
  • 后端服务运行在服务器本机:127.0.0.1:48082

那么前端应该这样请求:

管理后台

前端请求:

text 复制代码
https://admin.example.com/admin-api/...

Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/admin-api/...

门户网站

前端请求:

text 复制代码
https://www.example.com/api/...

或者有些项目会写成:

text 复制代码
https://www.example.com/app-api/...

Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/api/...

或者:

text 复制代码
http://127.0.0.1:48082/app-api/...

三、为什么这样做更好

1. 后端地址不用暴露

用户只看到前端自己的域名,看不到真实后端地址和端口。

2. 避免跨域

因为前端和接口都走同一个域名或同源路径,浏览器不会拦截。

3. 更方便管理

以后后端换端口、换机器、换部署方式,只需要改 Nginx,不需要重新改前端代码。

4. 更安全

后端服务甚至可以只监听 127.0.0.1,完全不对公网开放。


四、前端配置文件怎么写

这一部分是很多新手最容易迷糊的地方。

你要记住一个核心原则:

前端不要直接写真实后端地址,而是写接口前缀。

也就是不要写:

js 复制代码
baseURL: 'http://127.0.0.1:48082'

或者:

js 复制代码
baseURL: 'http://后端域名'

而应该写成:

js 复制代码
baseURL: '/admin-api'

或者:

js 复制代码
baseURL: '/api'

这样前端发请求时,请的就是当前站点自己的域名,再由 Nginx 去转发。


五、门户网站前端配置文件示例

你给出的门户配置文件是这样的:

js 复制代码
// 配置文件
export const config = {
  // 开发环境用完整地址,生产环境通过 nginx 转发
  baseURL: '/api',
  default_headers: 'application/json'
};

这个写法其实就是比较标准的生产环境写法

它的意思是:

  • 前端代码里请求接口时,统一走 /api
  • 浏览器实际访问时,会自动拼成当前域名下的 /api
  • Nginx 再把 /api 转发到真正的后端服务

例如:

前端代码里请求:

js 复制代码
config.baseURL + '/user/info'

最终就是:

text 复制代码
/api/user/info

浏览器实际发出的请求是:

text 复制代码
https://www.example.com/api/user/info

然后 Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/api/user/info

门户网站推荐写法

js 复制代码
// 配置文件
export const config = {
  // 生产环境通过 nginx 转发到后端
  baseURL: '/api',
  default_headers: 'application/json'
};

如果你的门户项目开发环境和生产环境要区分

也可以写成这种方式,更容易理解:

js 复制代码
const isDev = process.env.NODE_ENV === 'development';

export const config = {
  baseURL: isDev ? 'http://127.0.0.1:48082/api' : '/api',
  default_headers: 'application/json'
};

这样含义就很清楚:

  • 本地开发时,前端直接请求本地后端
  • 生产环境部署后,前端只请求 /api
  • 由 Nginx 去转发

六、芋道管理后台前端配置文件示例

芋道管理后台通常是 Vite 项目,很多时候会在 .env 文件里配接口地址。

比如原来有人会写成:

env 复制代码
VITE_BASE_URL='http://localhost:48082'
VITE_API_URL=/admin-api

这个就有问题。

因为它会导致前端最终请求:

text 复制代码
http://localhost:48082/admin-api/...

浏览器里这个 localhost 指向的是用户自己电脑,不是服务器。


芋道管理后台推荐写法

env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api

这样最终拼接出来的地址就是:

text 复制代码
/admin-api/...

浏览器实际访问时会变成:

text 复制代码
https://admin.example.com/admin-api/system/captcha/get

然后由 Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/admin-api/system/captcha/get

芋道后台前端配置的理解方式

如果你的请求封装代码里是这样拼接的:

js 复制代码
baseURL = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL

那么:

env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api

最终结果就是:

js 复制代码
'' + '/admin-api' = '/admin-api'

这正是我们想要的效果。


芋道后台环境变量完整示例

env 复制代码
# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP)
NODE_ENV=production

VITE_DEV=true

# 请求路径
VITE_BASE_URL=''

# 文件上传类型:server - 后端上传,client - 前端直连上传,仅支持S3服务
VITE_UPLOAD_TYPE=server

# 接口地址
VITE_API_URL=/admin-api

# 是否删除debugger
VITE_DROP_DEBUGGER=false

# 是否删除console.log
VITE_DROP_CONSOLE=false

# 是否sourcemap
VITE_SOURCEMAP=true

# 打包路径
VITE_BASE_PATH=/

# 输出路径
VITE_OUT_DIR=dist

# 商城H5会员端域名
VITE_MALL_H5_DOMAIN=''

# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true

# GoView域名
VITE_GOVIEW_URL=''

这里最关键的只有两个:

env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api

七、管理后台 Nginx 配置示例

假设:

  • 管理后台域名:admin.example.com
  • 前端静态文件目录:/www/wwwroot/admin-web/dist
  • 后端服务:127.0.0.1:48082
nginx 复制代码
server {
    listen 80;
    server_name admin.example.com;

    root /www/wwwroot/admin-web/dist;
    index index.html index.htm;

    # 管理后台接口转发
    location /admin-api/ {
        proxy_pass http://127.0.0.1:48082/admin-api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 如果项目有 websocket,可加这个
    location /infra/ws/ {
        proxy_pass http://127.0.0.1:48082/infra/ws/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 前端单页应用刷新防 404
    location / {
        try_files $uri $uri/ /index.html;
    }
}

八、门户网站 Nginx 配置示例

如果你的门户配置文件里写的是:

js 复制代码
baseURL: '/api'

那 Nginx 就应该把 /api 转发到后端。

假设:

  • 门户网站域名:www.example.com
  • 前端静态文件目录:/www/wwwroot/portal-web/dist
  • 后端服务:127.0.0.1:48082
nginx 复制代码
server {
    listen 80;
    server_name www.example.com;

    root /www/wwwroot/portal-web/dist;
    index index.html index.htm;

    # 门户接口转发
    location /api/ {
        proxy_pass http://127.0.0.1:48082/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 前端单页应用刷新防 404
    location / {
        try_files $uri $uri/ /index.html;
    }
}

九、前端配置和 Nginx 配置要一一对应

这是最重要的一点之一。

管理后台

如果前端写的是:

env 复制代码
VITE_API_URL=/admin-api

那么 Nginx 就必须写:

nginx 复制代码
location /admin-api/ {
    proxy_pass http://127.0.0.1:48082/admin-api/;
}

门户网站

如果前端写的是:

js 复制代码
baseURL: '/api'

那么 Nginx 就必须写:

nginx 复制代码
location /api/ {
    proxy_pass http://127.0.0.1:48082/api/;
}

不能乱配

比如前端写的是:

js 复制代码
baseURL: '/api'

但 Nginx 却只配了:

nginx 复制代码
location /admin-api/

那前端请求 /api/... 时,Nginx 根本接不住,请求自然就失败了。

所以一定要记住一句话:

前端 baseURL 写什么,Nginx 就要代理什么。


十、后端最好只监听本机

既然前端已经通过 Nginx 转发到后端,那么后端就没必要再对公网暴露。

例如 Spring Boot 可以这样配置:

yaml 复制代码
server:
  port: 48082
  address: 127.0.0.1

这样意味着:

  • 外部用户无法直接访问 48082
  • 只能通过 Nginx 代理访问
  • 更安全,也更规范

十一、为什么页面刷新会 404

很多 Vue 项目部署后,进入某个页面没事,但一刷新就 404。

例如访问:

text 复制代码
https://admin.example.com/system/user

前端路由能正常展示。

但刷新时,浏览器会直接请求服务器上的 /system/user 文件。

服务器发现没有这个真实文件,就返回 404。

解决办法就是:

nginx 复制代码
location / {
    try_files $uri $uri/ /index.html;
}

这句的意思是:

  • 先找真实文件
  • 再找真实目录
  • 都没有就返回 index.html

然后再由 Vue Router 接管页面路由。


十二、常见错误排查

1. 前端还在请求 localhost

说明前端配置没有改对,或者改完后没有重新打包。

重点检查:

芋道后台
env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api
门户网站
js 复制代码
baseURL: '/api'

2. 页面正常,接口 404

说明 Nginx 没有正确代理接口路径。

检查:

  • 前端写的是 /admin-api 还是 /api
  • Nginx 有没有对应的 location
  • proxy_pass 路径是否一致
  • 后端服务是否真的运行在 127.0.0.1:48082

3. 刷新页面 404

说明没有写:

nginx 复制代码
try_files $uri $uri/ /index.html;

4. 接口返回的是 HTML 页面

这通常说明接口请求没有匹配到代理规则,而是被:

nginx 复制代码
location / {
    try_files $uri $uri/ /index.html;
}

接住了。

本质上就是接口代理规则写错了,或者顺序有问题。


5. 改了 Nginx 配置但没有生效

每次改完配置后,都要执行:

bash 复制代码
nginx -t

检查配置语法。

没问题后再执行:

bash 复制代码
nginx -s reload

重新加载配置。


十三、最容易理解的一套最终方案

管理后台前端配置

env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api

管理后台 Nginx

nginx 复制代码
location /admin-api/ {
    proxy_pass http://127.0.0.1:48082/admin-api/;
}

门户网站前端配置

js 复制代码
export const config = {
  baseURL: '/api',
  default_headers: 'application/json'
};

门户网站 Nginx

nginx 复制代码
location /api/ {
    proxy_pass http://127.0.0.1:48082/api/;
}

最终效果

管理后台

浏览器请求:

text 复制代码
https://admin.example.com/admin-api/system/captcha/get

Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/admin-api/system/captcha/get
门户网站

浏览器请求:

text 复制代码
https://www.example.com/api/user/info

Nginx 转发到:

text 复制代码
http://127.0.0.1:48082/api/user/info

十四、总结

芋道项目和门户网站在部署时,不要让前端直接写真实后端地址,更不要写 localhost

正确方式是:

  • 前端请求自己的域名
  • 接口使用相对路径,例如 /admin-api/api
  • Nginx 负责把请求转发到真正的后端服务
  • 前端路由通过 try_files 解决刷新 404
  • 后端只监听 127.0.0.1,不直接暴露公网

一句话总结:

前端只认自己的域名,后端由 Nginx 在服务器内部转发。


十五、可直接复制的最简模板

管理后台前端配置

env 复制代码
VITE_BASE_URL=''
VITE_API_URL=/admin-api

管理后台 Nginx

nginx 复制代码
server {
    listen 80;
    server_name admin.example.com;
    root /www/wwwroot/admin-web/dist;
    index index.html;

    location /admin-api/ {
        proxy_pass http://127.0.0.1:48082/admin-api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}

门户网站前端配置

js 复制代码
export const config = {
  baseURL: '/api',
  default_headers: 'application/json'
};

门户网站 Nginx

nginx 复制代码
server {
    listen 80;
    server_name www.example.com;
    root /www/wwwroot/portal-web/dist;
    index index.html;

    location /api/ {
        proxy_pass http://127.0.0.1:48082/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}

相关推荐
huabiangaozhi2 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端
麦芽糖02192 小时前
centos虚拟机忘记密码怎么办
linux·运维·centos
umeelove352 小时前
Spring boot整合quartz方法
java·前端·spring boot
小码哥_常2 小时前
Android 开发探秘:View.post()为何能获取View宽高
前端
爱学习的程序媛2 小时前
【Web前端】WebAssembly详解
前端·web·wasm
DX_水位流量监测2 小时前
德希科技农村供水工程水质在线监测方案
大数据·运维·网络·水质监测·水质传感器·水质厂家·农村供水水质监测方案
不会写DN3 小时前
Js常用的字符串处理
开发语言·前端·javascript
晓13133 小时前
第三章 TypeScript 高级类型
前端·javascript·typescript
学术小白人3 小时前
EI会议征稿!2026年数字能源与转换技术国际研讨会(DECT 2026)
运维·自动化·能源·rdlink研发家·数字能源
ken22323 小时前
ubuntu 云镜像 2604 的内存和磁盘占用 实测
linux·运维·ubuntu