问题是这样的:
我使用了 vue3+vite 开发,vite 配置了代理如下:
proxy: {
'^/api*': {
target: 'http://localhost:9961/',
changeOrigin: true,
// 替换掉/api 路径
rewrite: (path) => path.replace(/^\/api/, ''),
}
}
以上在本地开发时一切很美好,都正常,但是! 当打包成静态资源部署上服务器后恶心的就来了 vite 的代理失效了,访问路径变成了前端页面路径+/api/xxx ,查了一下这种情况需要使用 nginx 代理/api 路径,然后转发到后台服务。
但是啊,我做的这个东西部署条件不支持装 nginx 啊,就不能直接访问后端接口吗?我后端接口都已经配置好了允许跨域,不管我是写死路径还是删除 vite 的 proxy 配置,最终打包后都会给我把请求路径替换成 /api/xxx
我只想要直接请求后端接口为啥这么难?
还有个让我很不解的地方,为啥用npm run preview
一切都正常,我配好的后端接口地址也会正常请求,一旦放到服务器上就又变成了/api/xxx
![]() |
1
Baymaxbowen 59 天前
你这个 proxy 只是本地的,线上不行,如果你不需要 api 的话,你可以在本地不加 api 的前缀
|
![]() |
2
loserc6 59 天前
接口地址与代理没关系,你看看你接口地址怎么写的吧
|
![]() |
3
sjhhjx0122 59 天前
不管是 dev 还是 preview 只是本地代理,你应该配个环境变量来区分你的开发环境和正式环境请求前缀
|
![]() |
4
zhtyytg 59 天前
proxy 本来就是开发服务器的代理
|
![]() |
5
tog 59 天前
不要开代理好了,服务端跨域直接放开
|
![]() |
6
ReinerShir OP @sjhhjx0122 配置了的,.env.production ,然后接口地址用的是变量,打包命令用的 npm run build --production
但是不管我怎么折腾,部署上去后都变成了/api/xxx |
7
PeakGao666 59 天前
我有个好办法,直接让后端做一层 api 反代不就完了
|
![]() |
8
Vegetable 59 天前
你发送请求的地方使用了相对地址,比如登录,你写的是 /login 。
把这个地址改成绝对地址,比如 http://www.baidu.com/login ,这样打包出来的页面就会访问绝对地址了。 接下来你会面临另一个问题,开发环境怎么办?如果你的所有环境都配置了 cors ,那你可以直接删除这个 proxy ,让页面直连服务器就可以了。你还需要通过通过 VITE_ENV 控制当前是什么环境,来访问不同的后端地址。 进一步,你还要考虑怎么在打包期间传入生产地址,而不是写死在代码或者 vite.config 里边。建议找一个开源的管理后台项目学习一下他们的 http 部分代码。 |
9
Elissa 59 天前
@ReinerShir
1. proxy 代理只是本地的代理 2. 本地运行时会通过 proxy 配置将接口地址中 api 替换成空的,打包后的和 proxy 代理就没关系了,不会替换字符串,也不会代理 3. 线上总是出现/api/xxx ,检查下.env.production 中接口地址是不是包含了 api |
![]() |
10
murmur 59 天前
我们的后端接口都是全跨域支持,因为要给移动端用,移动端是虚拟的 http 服务器随机端口,没有域名这一说
所以不代理也可以访问 搞那么麻烦干嘛 |
11
sseven 59 天前
我感觉这个 proxy 的配置不是一个好的实践,api 开头,代理又要去掉 api ,那何必要写 api ?
如果有些必须理由要 api 开头,用一个类似 baseUrl,commonPrefix 的东西,再通过环境变量来区分 build 和 dev 比较好控制 |
![]() |
12
Vegetable 59 天前
没注意看,你还配置了 rewrite ,在后端无法配合你的情况下你不能这么做。你现在不得不从两个选项里选一个
1. 后端网关处理/api 2. 去掉代理,前端代码去掉/api |
13
sleepm 59 天前
不要打包(除非线上和开发环境没啥区别,包括环境变量,后端)
在服务器 build 访问路径写成和后端一样的 代理是为了本地开发解决跨域,服务器上不需要解决跨域,就不需要配置代理 |
![]() |
14
zhhqiang 59 天前
request.js 文件 域名 打包的时候 指定成 你的服务端地址呢。
|
![]() |
15
BiChengfei 59 天前
桀桀桀,现在的前端是这样的
|
16
xiaowunai 59 天前
vite 的代码,只是在开发环境的时候用 node 帮你转发了一次,跨域只是浏览器规则限制
当你打包完了以后,就是一个前端项目,跨域你自然要用 nginx 什么的处理 所以你以前真的是后端么? |
![]() |
17
pelloz 59 天前 ![]() 额,你真的是后端么...
|
![]() |
18
NoManPlay 59 天前
开发环境和生产环境通过环境变量配置区分就行了
|
19
wyl986 59 天前 via iPhone
用 nginx 转发一下/api 到后端就完了,最简单最通用,不需要改任何代码
|
20
zhhbstudio 59 天前
我觉得这事有很大原因是 proxy 上层 key 从 devServe 改为 server 了。
这个 proxy 配置只是给你开发时候方便调试用的。。。 |
![]() |
21
shizhibuyu2023 59 天前
这是开发环境 vite 给你开的反向代理,解决跨域和路径问题。线上你没有反向代理的话,你需要先解决跨域问题,然后在后端处理 /api 啊,用中间件之类的把这个前缀去掉
|
22
jones2000 59 天前
后台把跨域限制关掉呗
|
![]() |
23
CHTuring 59 天前 ![]() 你身为后端就应该明白,跨域和 Vite 这种打包器无关,甚至和前端无关。
Vite 本地开发可以 proxy 完全是 Vite 方便开发人员而做的功能。 你要做的是在把这些代码删掉,然后后端开启跨域白名单,或者配置 Ngnix |
![]() |
24
microchang 59 天前
。。。注意下项目里面,应该有个.env.production 文件,里面 VITE_API_URL = 怎么配的看一下
|
![]() |
25
shadowyue 59 天前
哥你真是后端吗?跨域完完全全是需要后端来处理的。。。前端改不了一点,这是浏览器对 http 请求的安全规范。
|
![]() |
26
suyuyu 59 天前
感觉你直接就不明白跨域
|
![]() |
27
suyuyu 59 天前
看错了,抱歉,我自己打嘴 (
|
28
KongLiu 59 天前
CORS 了解一下
|
![]() |
29
Ritr 59 天前
production 环境变量没弄好
|
30
1183460943 59 天前
本地代理就是给开发时候用的啊, 环境上要不用 nginx 搞个同样逻辑的代理,要不服务端开 CORS
|
![]() |
31
wisetc 59 天前 via iPhone
你的配置没错,不过那个只是 devsever ,可不是生产环境哦,打包得另求,而且前端调用后段 api 真的需要 proxy 吗,明白了,是为了设置 origin 吧,那么是不是前端代码那里写错了呢,proxy 配置是魔改,前端代码打包才是真实
|
![]() |
32
ocyang1845 59 天前
你可以把你的 两个环境的 env 文件 相关内容贴出来看下
|
33
bsg1992 58 天前
proxy 只用于开发环境啊 ,生成还是得指定 host 。 不指定 host 肯定用的当前部署的 host 作为请求地址啊
|
34
cin 58 天前
配置个应用到 生产环境使用的 API_URL 变量, 或者打包时把前端输出到后端的 public 目录.
|
35
jspatrick 58 天前
如果你用的是 axios ,感觉你需要配置的是 baseURL ,通过环境变量切换不同的 baseURL
|
36
xitler 58 天前
你这个环境不支持 nginx 的话,那你打包出来的 dist 打算用啥东西访问
|
37
NessajCN 58 天前
你 po 一下后端接口我看看你怎么设置允许跨域的
|
![]() |
38
78786381 58 天前 ![]() @sseven nginx 为什么要有 rewrite ,不是因为后端所有的开头地址没有 api ,然后去除的吗?为什么写 api 开头,因为不写 api 开头你知道什么是页面,什么是请求吗
|
![]() |
39
unco020511 58 天前
我们现在都是代码里直接用线上域名,然后开发机器上通过代理工具(比如 whistls)来处理跨域和环境区分,代码无需任何区分
|
40
shunia 58 天前
不是,你到底有没有代码控制权啊,给我整蒙了。。。
如果实在不能改代码,那我能理解这是咋回事,不然好像有点。。。 前端非要请求/api 下的接口?后端非不提供/api 的接口? |
![]() |
41
unco020511 58 天前
说实话作为一个前端新人,我一直也每没明白这个 proxy 配置是怎么个配置,经常看到先加一个 api,然后又 rewrite 去掉 api,不太理解
|
![]() |
42
78786381 58 天前
@unco020511 #41 加 api 是本地开发的时候用来做请求代理,让访问 api 的请求自己不处理,都走代理,rewrite 掉 api 是因为后端的接口地址没有 api ,如果后端有地址有 api 比如用 tomcat 启动的这种,加上 api 就可以删除 rewrite
|
![]() |
43
TimPeake 58 天前
摒除跨域/前端本地开发代理方便等原因 ,api 前缀相关问题,出现这个问题的根本原因是因为你的后端项目接口没有统一的路由前缀,有统一的前缀,你这个问题就好理解了。
|
![]() |
44
unco020511 58 天前
@78786381 #42 那么在实际发起接口请求时,是用带域名的全路径还是相对路径?发起请求时,域名需要区分环境吗
|
![]() |
45
5200 58 天前
你这个问题问的,让前端和后端都看懵了😂
|
46
Marthemis 58 天前
1.为什么要加上/api ,而又去掉/api
|
![]() |
47
kyznever 58 天前
后端搞个 CORS 。还要啥代理啊
|
48
Marthemis 58 天前
1.为什么要加上/api ,而又去掉/api
是因为前端想在开发时去代理全部的 api 接口而不去代理静态资源等请求(其实这里用 /proxy 前缀更合适)但是后端的接口一般不带前缀。 2.如何避免后端配合前端改动,例如要求后端接口统一加上 /api 前缀 可以在前端的请求库例如 axios 配置一个 baseURL,写上 process.env.node_env === 'development' ? '/api' : '/'(或者后端接口部署的服务器域名) |
49
Marthemis 58 天前
至于为什么会发展出这些前端代理,是因为以前有很多后端(特指水平差的)不懂跨域也不愿意帮助去解决跨域...
|
![]() |
50
JayZXu 58 天前
静态资源托管的地方都能配置反向代理:无论是传统的 nginx ,Apache 或者后端服务都能做到
|
51
Marthemis 58 天前
当然了,你这里的情况一定是接口 url 前配置了/api (直接或者间接)。开发环境被 rewrite 了而生产环境没有。可以根据这个思路去找一下各个配置文件或者代码文件
|
![]() |
52
78786381 58 天前
@unco020511 #44 都可以,看运维和你们前后端安排,都可以完成这个工作
|
![]() |
53
MoonWalker 58 天前 ![]() 说句不爱听的....跟后端初学不初学的无关
|
55
GOURIDE 58 天前 ![]() 后端不是有拦截器过滤器么,直接改响应头跟 nginx 效果一个样。问题很小白
|
![]() |
56
DOLLOR 58 天前 via Android
vite 里的“代理”,是给 coding 时候用的,又不是给你打包上生产的时候用的。
你打包之后,它肯定管不了你配置的那些东西了。 |
![]() |
57
sgiyy 58 天前
|
58
hm20062006ok 58 天前
临时办法是: "在本地开发时一切很美好" , 保持现有不要改动。 打包正式环境时: 请求库用的 Axio 吧? 把 baseURL 写死成 https://example.com/xxxx. 比如 login 接口完整的地址是:https://example.com/api/login ,login 方法传递的 path 是‘’/login', 那么 baseURL 就填写:https://example.com/api 。 打包完再把 baseURL 改回来。 改来改去很麻烦? 你再去研究为什么要配置 env 吧
|
![]() |
59
zhw2590582 58 天前
既然这样,建议开发阶段不要使用 proxy ,统一让后端配置跨域
|
![]() |
60
abcde123456789 58 天前
如果后端允许跨域,就不需要设置 proxy ,开发环境和正式环境都不需要
后端允许跨域和 proxy 只存在一个就行了,都有的话会出错 |
61
gp0119 58 天前
你的接口是不需要 /api 前缀的?在 axios 配置文件 baseURL 里去掉 /api, 在 proxy 配置文件 target 里路径后面加上 api ,估计测试环境里刚好把你 baseURL 里 /api 前缀替换掉了
|
![]() |
62
ColdBird 58 天前
你后端允许跨域,那就配置网络请求的全路径不要用资源域名就得了呗,这点东西搞不明白吗?大部分后端接口不允许跨域,所以才需要访问资源域名,在资源域名通过 nginx 配置代理。
|
![]() |
63
bojackhorseman 58 天前
@unco020511 #40
我一般都是在 .env 文件里配置一个 VITE_APP_HOST , 本地开发 .env.development 里 VITE_APP_HOST=/api 正式环境的 .env.production VITE_APP_HOST=正式环境接口地址 然后在 axios 里 axios.defaults.baseURL = import.meta.env.VITE_APP_API_HOST ,vite 配置按照楼主写的,target 设置为测试环境接口地址 这样请求的时候本地开发请求 /api 会被 vite 代理到测试环境下而没有跨域问题。打包部署到线上请求的就是正式环境接口,更不会有跨域问题。 |
![]() |
64
bojackhorseman 58 天前
@bojackhorseman axios.defaults.baseURL = import.meta.env.VITE_APP_HOST ,手误
|
65
sseven 58 天前
@78786381 #38 我意思是:用的地方 request('a/c'),别带 api ,request 中统一加 api 前缀。这样方便控制前缀。而不要在代码中写 request('api/a/c'). 大概率是个单页应用,是不是就不用区分页面还是请求
|
![]() |
67
laobobo 58 天前
我知道为啥有人发了帖子说 跨域问题了
|
![]() |
68
shengchao 58 天前
作为前端,我很难理解后端对此有什么困惑的?
|
![]() |
69
monologue520 58 天前
按照你的思路解决这个问题需要使用环境变量,在前端加 baseURL 的地方通过变量做下判断就可以了
|
70
kanepan19 58 天前
|
![]() |
71
0xD800 57 天前
你是给 axios 配置了 baseUrl='/api'吧,
我建议你了解基本的技术原理。 1. vue-router 的 history 模式,如果你是部署在后端应用中,比如放在 springboot 的 static 文件夹内,建议你直接设置为 webhashhistory ,否则你要手动处理路由,我觉得你可能会花费更多时间 2. vite 的 build.base ,这个是打包的时候把里面的引用文件都加上这个前缀,应用场景:把前端部署在某个域名的/xx 文件夹下,通过 www.example.com/xx/index.html 访问,此时也要主要 vue-router 的 history 的 base 参数 3. axios 的 baseUrl:这个是 API 接口的前缀,你可以控制在本地环境使用/api 前缀,然后用 proxy 拦截/api 前缀再转发。生产环境配置其他的 baseUrl 或者不配,看你后端地址怎么访问 |