对于前后分离的项目来说,产生浏览器跨域问题简直是家常便饭。自己跟小伙伴写的一个小项目,也时常产生跨域问题,以往都是叫后端的伙伴解决。最近尝试从前端解决跨域问题,直到现在才解决,在这里总结一下解决的方案。
本文分本地开发解决跨域以及服务器解决跨域。
本地开发解决跨域问题
开发的过程中,可以使用vuecli3的devServer–proxy进行代理解决跨域问题。(vuecli2也有相同的配置方法。)
在项目的目录中创建vue.config.js
文件,文件内容为:
module.exports = {
devServer: {
// 使用代理解决跨域问题
proxy: {
'/api': {
target: 'http://81.69.xx.xxx',
changeOrigin: true,
pathRewrite: {
"^/api": '/'
}
}
},
}
}
上面这段进行代理的代码表示,当遇到请求为/api
开头的地址时候,将代理到http://81.69.xx.xxx
上面去。(这里,target
后面的ip地址表示进行跨域请求的ip地址,比如此处的http://81.69.xx.xxx
就是我后端小伙伴的服务器ip地址。)
比如本地的一个请求地址为:
/api/user/login
实际上会代理请求到:
http://81.69.xx.xxx/user/login
也因为这样,书写请求地址的时候,必须以/api
开头,不然将请求不成功。
但是,这种方法在项目打包(build)之后,代理将失效,所以仅适合本地开发使用!
部署到服务器解决跨域问题
这里使用nginx反向代理解决跨域问题。
首先服务器中需要安装好nginx以及项目部署的部署,关于服务器中nginx的安装部署vue项目可以参考文章:https://blog.csdn.net/weixin_44303404/article/details/113523794
对nginx配置文件进行配置:
// 我的nginx配置文件
server {
listen 80;
server_name 49.234.xxx.xxx;
# 更改配置,匹配路径,修改index.html的名字,用于区分该配置文件替换了容器中的配置文件
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# 增加下面一条语句,用来解决页面刷新404的问题
try_files $uri $uri/ /index.html;
}
# 解决跨域问题
location /api/ {
proxy_pass http://81.69.xx.xxx/;
}
}
重点要看到
server_name 49.234.xxx.xxx;
以及
# 解决线上跨域问题
location /api/ {
proxy_pass http://81.69.xx.xxx/;
}
这两处的作用是,当请求地址为http://49.234.xxx.xxx/api
开头的时候,将代理到http://81.69.xx.xxx/
。
其中49.234.xxx.xxx
是我的前端项目地址,81.69.xx.xxx
是后端项目地址。
因此,部署到服务器项目的请求,应该都以http://49.234.xxx.xxx/api
开头。
proxy_pass http://81.69.xx.xxx/;
尤其注意代理的地址最后面一定要带上 /
Tips
为了避免由于开发以及发布解决跨域问题的方式不同而反复修改配置文件,可以对axios的地址进行灵活配置。
比如在本地开发环境下,对vue.conf.js
配置如下:
module.exports = {
outputDir: 'dist', //build输出目录
assetsDir: 'assets', //静态资源目录(js, css, img)
lintOnSave: false, //是否开启eslint
devServer: {
// 指定端口
port: 8086,
// 直接打开浏览器
open: true,
// 使用代理解决跨域问题
proxy: {
'/api': {
target: 'http://81.69.27.130',
changeOrigin: true,
// 下面这行注释掉本地也会出现404
pathRewrite: {
"^/api": '/'
}
}
},
}
}
axios的配置如下:
const isProduction = process.env.NODE_ENV === 'production'
let axiosDemo = axios.create({
// 如果判断是生产环境,则使用第一个,否则为空
baseURL: isProduction ? 'http://49.234.xxx.xxx' : '',
responseType: `json`,
headers: {
"Content-Type": "application/json",
}
});
请求url书写如下:
axiosDemo.get('/api/user/login');
这样,在本地开发的时候,把baseURL
注释掉,build项目之前,加上baseURL
,再发布到服务器中(服务器记得也做好相应的配置)。