vue3中的配置代理

Posted qq_45334976

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue3中的配置代理相关的知识,希望对你有一定的参考价值。

 如图,配置代理就是在客户端与服务器中充当中介的角色

目录

关于配置代理,首先我们的要知道为什么要配置代理,配置代理做了什么事情

一、跨域是什么

二、如何解决

三、配置代理案例

       1. 下面是我自己在后端尝试解决跨域的例子

2.然后在vue中解决跨域是在vue-cli中的 vue.config.js中配置代理,


关于配置代理,首先我们的要知道为什么要配置代理,配置代理做了什么事情

        1.首先,为什么要配置代理。 大家应该都写过axios请求吧,当我们向后台服务器发送axios请求的时候,有时候会在浏览器中报错这样一段话

 这就是由于我们发送的请求跨域了, 跨域并不是 就 请求发不出去 或  服务器的响应接受不到,而是 由于 浏览器 服务器发送的请求 跨域了,导致 浏览器在接受到服务器的响应数据后拦截了下来,不给你。

        所以 简单点说 , 配置代理就是为了让浏览器接受到服务器的数据后发送给我们。

同源策略分为以下两种:

  1. DOM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
  2. XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。       

关于详细的大家可以看  什么是同源策略? - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/66047383

        2.配置代理做了什么。配置代理就是找一台代理服务器,在你发送请求的时候做一个中介,浏览器先将请求发送给代理服务器,代理服务器再将请求转发给后台的数据服务器。代理服务器 要和 你真正访问的 后台服务器是同源的。

关于跨域我给大家从vue的文档中截取的这么一段

一、跨域是什么

跨域本质是浏览器基于同源策略的一种安全手段

同源策略(Sameoriginpolicy),是一种约定,它是浏览器最核心也最基本的安全功能

所谓同源(即指在同一个域)具有以下三个相同点

  • 协议相同(protocol)
  • 主机相同(host)
  • 端口相同(port)

反之非同源请求,也就是协议、端口、主机其中一项不相同的时候,这时候就会产生跨域

一定要注意跨域是浏览器的限制,你用抓包工具抓取接口数据,是可以看到接口已经把数据返回回来了,只是浏览器的限制,你获取不到数据。用postman请求接口能够请求到数据。这些再次印证了跨域是浏览器的限制

二、如何解决

解决跨域的方法有很多,下面列举了三种:

  • JSONP
  • CORS
  • Proxy

而在vue项目中,我们主要针对CORSProxy这两种方案进行展开

CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源

只要后端实现了 CORS,就实现了跨域

所以 CORS  解决跨域是在后端解决的

三、配置代理案例

       1. 下面是我自己在后端尝试解决跨域的例子

从左边的窗口 ,我们可以看到 我们用express在nodejs环境下搭建了一个简单的服务器 ,并且没有使用cors中间件,解决跨域

所有 如下图所示,我们成功报错了

然后,我们在express搭建的服务器中,使用cors中间件,然后重启服务

 然后结果也是如我们所料,并没有报跨域的错误

 OK,到这里我们在服务端解决跨域问题就解决了

2.然后在vue中解决跨域是在vue-cli中的 vue.config.js中配置代理,

                注意!!! 在vue.config.js中配置代理只适用于开发环境,如果大家把项目进行打包后,devServer就没有用了,该报错的还是会报错,但是 在打包后的生产环境中,我们还是有解决方法的

        

        如图,我们也是在服务器中重新注释掉了cors中间件,在vue.config.js中也没有配置代理。

         那我们也是如愿以偿再次报错。

然后,我们再在vue.config.js中配置proxy代理,添加了这段代代码,且在发送请求时,我们也要在请求的url上 携带上 /bpi 

"/bpi":  // 代理接口前缀为/bpi的请求
        "target": 'http://localhost:8080', // 对应的代理地址
        "secure": false, // 接受运行在https上,默认不接受
        "changeOrigin": true, // 如果设置为true,那么本地会虚拟一个服务器接收你的请求并代你发送该请求,这样就不会有跨域问题(只适合开发环境)
        "pathRewrite":  //重写路径 比如'/apis/aaa/ccc'重写为'/aaa/ccc'
          '^/bpi': ""
        
      ,

这样我们在开发环境下的配置代理就完成了

 

 在生产环境下的我就懒得写了,大家可以看下面的,里面有更好的解释

面试官:Vue项目中你是如何解决跨域的呢? | web前端面试 - 面试官系列 (vue3js.cn)https://vue3js.cn/interview/vue/cors.html#%E4%BA%8C%E3%80%81%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3

        

Vue中的Ajax

文章目录


本案例需要下载axios库: npm install axios

Vue脚手架配置代理

为什么要配置代理服务器

什么是跨域?

跨域资源共享(英语:Cross-origin resource sharing,缩写:CORS),用于让网页的受限资源能够被其他域名的页面访问的一种机制。 --摘自维基百科
跨域的基本三要素:

  • 同域名
  • 同端口
  • 同协议

通俗理解:
我们从站点A对其他站点进行网络请求时,浏览器端和服务端需要对这个请求进行处理,保证这个请求是安全的。 这个处理就是跨域

为什么需要跨域

跨域是为了保证请求的安全作出的策略。

  • 浏览器请求必须遵循同源策略: 同一域名、同一端口、同一协议

跨域方案

  • JSONP跨域
  • CORS跨域
  • 代理跨域

代理跨域

我们的客户端想访问A服务器,但是A服务器存在跨域问题,我们就再开一个同源的代理服务器B,我们把请求给B服务,然后B服务器去访问A服务器,A处理好信息返回给B,B再将数据返回给客户端

跨域问题是前端存在的问题,而我们服务器之间传递信息直接是用http,是不存在什么跨域问题的

接口代理跨域特点

  • 服务端、客户端均不需要配置
  • 通过中间服务器(代理服务器)的配置实现(如Nginx、IIS、Apache)
  • 我们这里使用的Vue-CLI也能帮我们实现跨域处理

CORS跨域

  • CORS跨域个人是最常用的(多亏.NET Core对跨域策略的支持非常好用)。
  • CORS跨域是由服务端应用设置的一个跨域策略,比如开放指定的HTTP Method、指定请求方Url、指定请求携带的Headers必须包含的字段等等~。
  • CORS这种方式简单高效,合理的使用它的策略可以保证服务器的安全的同时也提升了前后端的开发体验~;

CORS跨域特点

  • 后端配置,前端直接请求;
  • 策略丰富,可支持多种策略,如HTTP方法、URL等;
  • 前后端交互方式非常规范;
  • 除了常用的GET、POST、HEAD 其他方法进行请求则需要发起OPTIONS请求对服务器端进行跨域允许的许可请求

利用Vue-CLI配置代理服务器

App.vue

<template>
    <div id="root">
        <button @click="getStudents">获取学生信息</button><br/>
        <button @click="getCars">获取汽车信息</button>
    </div>
</template>

<script>
    import axios from 'axios'
    
    export default 
        name:'App',
        methods: 
			getStudents()
				axios.get('http://localhost:8080/lscStudent/students').then(
					response => 
						console.log('请求成功了',response.data)
					,
					error => 
						console.log('请求失败了',error.message)
					
				)
			,
            getCars()
				axios.get('http://localhost:8080/lscCar/cars').then(
					response => 
						console.log('请求成功了',response.data)
					,
					error => 
						console.log('请求失败了',error.message)
					
				)
			
        
    
</script>

vue.config.js:

module.exports = 
  pages: 
      index: 
          entry: 'src/main.js',
      ,
  ,
  lintOnSave:false,
  // 开启代理服务器(方式一)
  // devServer: 
  //     proxy:'http://localhost:5000'
  // 

  //开启代理服务器(方式二)
devServer: 
      proxy: 
          '/lscStudent': 
              target: 'http://localhost:5000',
              pathRewrite:'^/lscStudent':'',
              // ws: true, //用于支持websocket,默认值为true
              // changeOrigin: true //用于控制请求头中的host值,默认值为true
          ,
          '/lscCar': 
              target: 'http://localhost:5001',
              pathRewrite:'^/lscCar':'',
              // ws: true, //用于支持websocket,默认值为true
              // changeOrigin: true //用于控制请求头中的host值,默认值为true
          
      
  

总结

方法一:在vue.config.js中添加如下配置:

devServer:
    proxy:"http://localhost:5000"

  • 优点:配置简单,请求资源时直接发给前端即可

  • 缺点:不能配置多个代理,不能灵活的控制请求是否走代理

    • 如果我们请求的数据再8080中存在,那么就直接用代理服务器的,不能访问目标服务器

    • 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二:

devServer: 
    proxy: 
      	'/api1':  // 匹配所有以 '/api1'开头的请求路径
        	target: 'http://localhost:5000',// 代理目标的基础路径
        	changeOrigin: true,
        	pathRewrite: '^/api1': ''
           // changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
			 // changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
      	,
      	'/api2':  // 匹配所有以 '/api2'开头的请求路径
        	target: 'http://localhost:5001',// 代理目标的基础路径
        	changeOrigin: true,
        	pathRewrite: '^/api2': ''
      	
    


说明:

  • 优点:可以配置多个代理,且可以灵活的控制请求是否走代理
  • 缺点:配置略微繁琐,请求资源时必须加前缀

GitHub用户搜索案例

public/index.html

<!DOCTYPE html>
<html lang="">
    <head>
        <meta charset="UTF-8">
        <!-- 针对IE浏览器的特殊配置,含义是让IE浏览器以最高渲染级别渲染页面 -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 开启移动端的理想端口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <!-- 配置页签图标 -->
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <!-- 引入bootstrap样式 -->
        <link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
        <!-- 配置网页标题 -->
        <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
        <!-- 容器 -->
        <div id="app"></div>
    </body>
</html>

  • 在这引入bootstrap样式,如果对应的一些样式没有,不会报错,比如字体什么的,如果在main.js中引入,会进行严格的检查,因为是ES6语法

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue(
    el:"#app",
    render: h => h(App),
    beforeCreate()
        Vue.prototype.$bus = this
    
)

App.vue

<template>
	<div class="container">
		<Search/>
		<List/>
	</div>
</template>

<script>
	import Search from './components/Search.vue'
	import List from './components/List.vue'

    export default 
       name:'App',
		components:Search,List,
	
</script>

search.vue

<template>
    <section class="jumbotron">
		<h3 class="jumbotron-heading">Search Github Users</h3>
		<div>
            <input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
            <button @click="getUsers">Search</button>
		</div>
    </section>
</template>

<script>
    import axios from 'axios'
    export default 
        name:'Search',
        data() 
            return 
                keyWord:''
            
        ,
        methods: 
            getUsers()
                //请求前更新List的数据
				this.$bus.$emit('updateListData',isLoading:true,errMsg:'',users:[],isFirst:false)
				axios.get(`https://api.github.com/search/users?q=$this.keyWord`).then(
					response => 
						console.log('请求成功了')
						//请求成功后更新List的数据
						this.$bus.$emit('updateListData',isLoading:false,errMsg:'',users:response.data.items)
					,
					error => 
						//请求后更新List的数据
						this.$bus.$emit('updateListData',isLoading:false,errMsg:error.message,users:[])
					
				)
            
        
    
</script>

List.vue

<template>
    <div class="row">
        <!-- 展示用户列表 -->
        <div class="card" v-show="info.users.length" v-for="user in info.users" :key="user.id">
            <a :href="user.html_url" target="_blank">
                <img :src="user.avatar_url" style='width: 100px'/>
            </a>
            <h4 class="card-title">user.login</h4>
        </div>
        <!-- 展示欢迎词 -->
        <h1 v-show="info.isFirst">欢迎使用!</h1>
        <!-- 展示加载中 -->
        <h1 v-show="info.isLoading">加载中...</h1>
        <!-- 展示错误信息 -->
        <h1 v-show="info.errMsg">errMsg</h1>
    </div>
</template>

<script>
    export default 
        name:'List',
        data() 
            return 
                info:
                    isFirst:true,
                    isLoading:false,
                    errMsg:'',
                    users:[]
                
            
        ,
        mounted()
            this.$bus.$on('updateListData',(dataObj)=>
                //动态合并两个对象的属性
                this.info = ...this.info,...dataObj
            )
        ,
        beforeDestroy()
            this.$bus.$off('updateListData')
        
    
</script>

<style scoped>
    .album 
		min-height: 50rem; /* Can be removed; just added for demo purposes */
		padding-top: 3rem;
		padding-bottom: 3rem;
		background-color: #f7f7f7;
	

	.card 
		float: left;
		width: 33.333%;
		padding: .75rem;
		margin-bottom: 2rem;
		border: 1px solid #efefef;
		text-align: center;
	

	.card > img 
		margin-bottom: .75rem;
		border-radius: 100px;
	

	.card-text 
		font-size: 85%;
	
</style>

总结:

vue项目常用的两个Ajax库:

  1. axios:通用的Ajax请求库,官方推荐,效率高
  2. vue-resource:vue插件库,vue 1.x使用广泛,官方已不维护

以上是关于vue3中的配置代理的主要内容,如果未能解决你的问题,请参考以下文章

Vue 3 & Composition API:v-for 循环中的模板引用错误:仅获取代理

linux中的网络配置

vue3中的配置代理

封装网络请求

Vue.js学习—— 分别从前后端Nginx解决SpringBoot+vue.js项目中的跨域问题

如何将 Vue 2 网站转换为 PWA 网络应用程序?