V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ReinerShir
V2EX  ›  Vue.js

后端初学 vue3+vite 快被这个打包+跨域问题烦死了!

  •  
  •   ReinerShir · 144 天前 · 9238 次点击
    这是一个创建于 144 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题是这样的:

    我使用了 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 条附言  ·  143 天前
    本题可以终结了,之前之所以没成功是因为部署平台的问题,新的静态资源部署上去总是不生效,导致我以为是 vite 的问题

    现在我在本地使用 proxy ,请求地址用环境变量判断是走/api 还是直接请求后端接口来解决了
    71 条回复    2024-07-12 09:43:28 +08:00
    Baymaxbowen
        1
    Baymaxbowen  
       144 天前
    你这个 proxy 只是本地的,线上不行,如果你不需要 api 的话,你可以在本地不加 api 的前缀
    loserc6
        2
    loserc6  
       144 天前
    接口地址与代理没关系,你看看你接口地址怎么写的吧
    sjhhjx0122
        3
    sjhhjx0122  
       144 天前
    不管是 dev 还是 preview 只是本地代理,你应该配个环境变量来区分你的开发环境和正式环境请求前缀
    zhtyytg
        4
    zhtyytg  
       144 天前
    proxy 本来就是开发服务器的代理
    tog
        5
    tog  
       144 天前
    不要开代理好了,服务端跨域直接放开
    ReinerShir
        6
    ReinerShir  
    OP
       144 天前
    @sjhhjx0122 配置了的,.env.production ,然后接口地址用的是变量,打包命令用的 npm run build --production
    但是不管我怎么折腾,部署上去后都变成了/api/xxx
    PeakGao666
        7
    PeakGao666  
       144 天前
    我有个好办法,直接让后端做一层 api 反代不就完了
    Vegetable
        8
    Vegetable  
       144 天前
    你发送请求的地方使用了相对地址,比如登录,你写的是 /login 。
    把这个地址改成绝对地址,比如 http://www.baidu.com/login ,这样打包出来的页面就会访问绝对地址了。

    接下来你会面临另一个问题,开发环境怎么办?如果你的所有环境都配置了 cors ,那你可以直接删除这个 proxy ,让页面直连服务器就可以了。你还需要通过通过 VITE_ENV 控制当前是什么环境,来访问不同的后端地址。

    进一步,你还要考虑怎么在打包期间传入生产地址,而不是写死在代码或者 vite.config 里边。建议找一个开源的管理后台项目学习一下他们的 http 部分代码。
    Elissa
        9
    Elissa  
       144 天前
    @ReinerShir
    1. proxy 代理只是本地的代理
    2. 本地运行时会通过 proxy 配置将接口地址中 api 替换成空的,打包后的和 proxy 代理就没关系了,不会替换字符串,也不会代理
    3. 线上总是出现/api/xxx ,检查下.env.production 中接口地址是不是包含了 api
    murmur
        10
    murmur  
       144 天前
    我们的后端接口都是全跨域支持,因为要给移动端用,移动端是虚拟的 http 服务器随机端口,没有域名这一说

    所以不代理也可以访问

    搞那么麻烦干嘛
    sseven
        11
    sseven  
       144 天前
    我感觉这个 proxy 的配置不是一个好的实践,api 开头,代理又要去掉 api ,那何必要写 api ?
    如果有些必须理由要 api 开头,用一个类似 baseUrl,commonPrefix 的东西,再通过环境变量来区分 build 和 dev 比较好控制
    Vegetable
        12
    Vegetable  
       144 天前
    没注意看,你还配置了 rewrite ,在后端无法配合你的情况下你不能这么做。你现在不得不从两个选项里选一个

    1. 后端网关处理/api
    2. 去掉代理,前端代码去掉/api
    sleepm
        13
    sleepm  
       144 天前
    不要打包(除非线上和开发环境没啥区别,包括环境变量,后端)
    在服务器 build
    访问路径写成和后端一样的
    代理是为了本地开发解决跨域,服务器上不需要解决跨域,就不需要配置代理
    zhhqiang
        14
    zhhqiang  
       144 天前
    request.js 文件 域名 打包的时候 指定成 你的服务端地址呢。
    BiChengfei
        15
    BiChengfei  
       144 天前
    桀桀桀,现在的前端是这样的
    xiaowunai
        16
    xiaowunai  
       143 天前
    vite 的代码,只是在开发环境的时候用 node 帮你转发了一次,跨域只是浏览器规则限制
    当你打包完了以后,就是一个前端项目,跨域你自然要用 nginx 什么的处理
    所以你以前真的是后端么?
    pelloz
        17
    pelloz  
       143 天前   ❤️ 34
    额,你真的是后端么...
    NoManPlay
        18
    NoManPlay  
       143 天前
    开发环境和生产环境通过环境变量配置区分就行了
    wyl986
        19
    wyl986  
       143 天前 via iPhone
    用 nginx 转发一下/api 到后端就完了,最简单最通用,不需要改任何代码
    zhhbstudio
        20
    zhhbstudio  
       143 天前
    我觉得这事有很大原因是 proxy 上层 key 从 devServe 改为 server 了。

    这个 proxy 配置只是给你开发时候方便调试用的。。。
    Xu3Xan89YsA7oP64
        21
    Xu3Xan89YsA7oP64  
       143 天前
    这是开发环境 vite 给你开的反向代理,解决跨域和路径问题。线上你没有反向代理的话,你需要先解决跨域问题,然后在后端处理 /api 啊,用中间件之类的把这个前缀去掉
    jones2000
        22
    jones2000  
       143 天前
    后台把跨域限制关掉呗
    CHTuring
        23
    CHTuring  
       143 天前   ❤️ 1
    你身为后端就应该明白,跨域和 Vite 这种打包器无关,甚至和前端无关。
    Vite 本地开发可以 proxy 完全是 Vite 方便开发人员而做的功能。
    你要做的是在把这些代码删掉,然后后端开启跨域白名单,或者配置 Ngnix
    microchang
        24
    microchang  
       143 天前
    。。。注意下项目里面,应该有个.env.production 文件,里面 VITE_API_URL = 怎么配的看一下
    shadowyue
        25
    shadowyue  
       143 天前
    哥你真是后端吗?跨域完完全全是需要后端来处理的。。。前端改不了一点,这是浏览器对 http 请求的安全规范。
    suyuyu
        26
    suyuyu  
       143 天前
    感觉你直接就不明白跨域
    suyuyu
        27
    suyuyu  
       143 天前
    看错了,抱歉,我自己打嘴 (
    KongLiu
        28
    KongLiu  
       143 天前
    CORS 了解一下
    Ritr
        29
    Ritr  
       143 天前
    production 环境变量没弄好
    1183460943
        30
    1183460943  
       143 天前
    本地代理就是给开发时候用的啊, 环境上要不用 nginx 搞个同样逻辑的代理,要不服务端开 CORS
    wisetc
        31
    wisetc  
       143 天前 via iPhone
    你的配置没错,不过那个只是 devsever ,可不是生产环境哦,打包得另求,而且前端调用后段 api 真的需要 proxy 吗,明白了,是为了设置 origin 吧,那么是不是前端代码那里写错了呢,proxy 配置是魔改,前端代码打包才是真实
    inc904
        32
    inc904  
       143 天前
    你可以把你的 两个环境的 env 文件 相关内容贴出来看下
    bsg1992
        33
    bsg1992  
       143 天前
    proxy 只用于开发环境啊 ,生成还是得指定 host 。 不指定 host 肯定用的当前部署的 host 作为请求地址啊
    cin
        34
    cin  
       143 天前
    配置个应用到 生产环境使用的 API_URL 变量, 或者打包时把前端输出到后端的 public 目录.
    jspatrick
        35
    jspatrick  
       143 天前
    如果你用的是 axios ,感觉你需要配置的是 baseURL ,通过环境变量切换不同的 baseURL
    xitler
        36
    xitler  
       143 天前
    你这个环境不支持 nginx 的话,那你打包出来的 dist 打算用啥东西访问
    NessajCN
        37
    NessajCN  
       143 天前
    你 po 一下后端接口我看看你怎么设置允许跨域的
    78786381
        38
    78786381  
       143 天前   ❤️ 1
    @sseven nginx 为什么要有 rewrite ,不是因为后端所有的开头地址没有 api ,然后去除的吗?为什么写 api 开头,因为不写 api 开头你知道什么是页面,什么是请求吗
    unco020511
        39
    unco020511  
       143 天前
    我们现在都是代码里直接用线上域名,然后开发机器上通过代理工具(比如 whistls)来处理跨域和环境区分,代码无需任何区分
    shunia
        40
    shunia  
       143 天前
    不是,你到底有没有代码控制权啊,给我整蒙了。。。
    如果实在不能改代码,那我能理解这是咋回事,不然好像有点。。。

    前端非要请求/api 下的接口?后端非不提供/api 的接口?
    unco020511
        41
    unco020511  
       143 天前
    说实话作为一个前端新人,我一直也每没明白这个 proxy 配置是怎么个配置,经常看到先加一个 api,然后又 rewrite 去掉 api,不太理解
    78786381
        42
    78786381  
       143 天前
    @unco020511 #41 加 api 是本地开发的时候用来做请求代理,让访问 api 的请求自己不处理,都走代理,rewrite 掉 api 是因为后端的接口地址没有 api ,如果后端有地址有 api 比如用 tomcat 启动的这种,加上 api 就可以删除 rewrite
    TimPeake
        43
    TimPeake  
       143 天前
    摒除跨域/前端本地开发代理方便等原因 ,api 前缀相关问题,出现这个问题的根本原因是因为你的后端项目接口没有统一的路由前缀,有统一的前缀,你这个问题就好理解了。
    unco020511
        44
    unco020511  
       143 天前
    @78786381 #42 那么在实际发起接口请求时,是用带域名的全路径还是相对路径?发起请求时,域名需要区分环境吗
    5200
        45
    5200  
       143 天前
    你这个问题问的,让前端和后端都看懵了😂
    Marthemis
        46
    Marthemis  
       143 天前
    1.为什么要加上/api ,而又去掉/api
    kyznever
        47
    kyznever  
       143 天前
    后端搞个 CORS 。还要啥代理啊
    Marthemis
        48
    Marthemis  
       143 天前
    1.为什么要加上/api ,而又去掉/api
    是因为前端想在开发时去代理全部的 api 接口而不去代理静态资源等请求(其实这里用 /proxy 前缀更合适)但是后端的接口一般不带前缀。
    2.如何避免后端配合前端改动,例如要求后端接口统一加上 /api 前缀
    可以在前端的请求库例如 axios 配置一个 baseURL,写上 process.env.node_env === 'development' ? '/api' : '/'(或者后端接口部署的服务器域名)
    Marthemis
        49
    Marthemis  
       143 天前
    至于为什么会发展出这些前端代理,是因为以前有很多后端(特指水平差的)不懂跨域也不愿意帮助去解决跨域...
    JayZXu
        50
    JayZXu  
       143 天前
    静态资源托管的地方都能配置反向代理:无论是传统的 nginx ,Apache 或者后端服务都能做到
    Marthemis
        51
    Marthemis  
       143 天前
    当然了,你这里的情况一定是接口 url 前配置了/api (直接或者间接)。开发环境被 rewrite 了而生产环境没有。可以根据这个思路去找一下各个配置文件或者代码文件
    78786381
        52
    78786381  
       143 天前
    @unco020511 #44 都可以,看运维和你们前后端安排,都可以完成这个工作
    MoonWalker
        53
    MoonWalker  
       143 天前   ❤️ 1
    说句不爱听的....跟后端初学不初学的无关
    Torpedo
        54
    Torpedo  
       143 天前
    @pelloz #17 在某些规模不小的厂,很多后端配跨域头都搞不定的。合作过的至少有 2 、30 不行
    GOURIDE
        55
    GOURIDE  
       143 天前   ❤️ 1
    后端不是有拦截器过滤器么,直接改响应头跟 nginx 效果一个样。问题很小白
    DOLLOR
        56
    DOLLOR  
       143 天前 via Android
    vite 里的“代理”,是给 coding 时候用的,又不是给你打包上生产的时候用的。
    你打包之后,它肯定管不了你配置的那些东西了。
    sgiyy
        57
    sgiyy  
       143 天前
    这个提问,能感觉你对后端也不是很懂
    hm20062006ok
        58
    hm20062006ok  
       143 天前
    临时办法是: "在本地开发时一切很美好" , 保持现有不要改动。 打包正式环境时: 请求库用的 Axio 吧? 把 baseURL 写死成 https://example.com/xxxx. 比如 login 接口完整的地址是:https://example.com/api/login ,login 方法传递的 path 是‘’/login', 那么 baseURL 就填写:https://example.com/api 。 打包完再把 baseURL 改回来。 改来改去很麻烦? 你再去研究为什么要配置 env 吧
    zhw2590582
        59
    zhw2590582  
       143 天前
    既然这样,建议开发阶段不要使用 proxy ,统一让后端配置跨域
    abcde123456789
        60
    abcde123456789  
       143 天前
    如果后端允许跨域,就不需要设置 proxy ,开发环境和正式环境都不需要

    后端允许跨域和 proxy 只存在一个就行了,都有的话会出错
    gp0119
        61
    gp0119  
       143 天前
    你的接口是不需要 /api 前缀的?在 axios 配置文件 baseURL 里去掉 /api, 在 proxy 配置文件 target 里路径后面加上 api ,估计测试环境里刚好把你 baseURL 里 /api 前缀替换掉了
    ColdBird
        62
    ColdBird  
       143 天前
    你后端允许跨域,那就配置网络请求的全路径不要用资源域名就得了呗,这点东西搞不明白吗?大部分后端接口不允许跨域,所以才需要访问资源域名,在资源域名通过 nginx 配置代理。
    bojackhorseman
        63
    bojackhorseman  
       143 天前
    @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 代理到测试环境下而没有跨域问题。打包部署到线上请求的就是正式环境接口,更不会有跨域问题。
    bojackhorseman
        64
    bojackhorseman  
       143 天前
    @bojackhorseman axios.defaults.baseURL = import.meta.env.VITE_APP_HOST ,手误
    sseven
        65
    sseven  
       143 天前
    @78786381 #38 我意思是:用的地方 request('a/c'),别带 api ,request 中统一加 api 前缀。这样方便控制前缀。而不要在代码中写 request('api/a/c'). 大概率是个单页应用,是不是就不用区分页面还是请求
    78786381
        66
    78786381  
       143 天前
    @sseven #65 那我估计你的理解还是错误的,proxy 那里设置 api 开头本来就是做区分的,是 node 处理还是代理,肯定不会每一个地方都写 api
    laobobo
        67
    laobobo  
       143 天前
    我知道为啥有人发了帖子说 跨域问题了
    shengchao
        68
    shengchao  
       143 天前
    作为前端,我很难理解后端对此有什么困惑的?
    monologue520
        69
    monologue520  
       143 天前
    按照你的思路解决这个问题需要使用环境变量,在前端加 baseURL 的地方通过变量做下判断就可以了
    kanepan19
        70
    kanepan19  
       143 天前
    0xD800
        71
    0xD800  
       142 天前
    你是给 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 或者不配,看你后端地址怎么访问
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2611 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 10:45 · PVG 18:45 · LAX 02:45 · JFK 05:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.