记:vite3+vue3+axios前端项目跨域问题解决【前端和服务器nginx配置】

avatar
作者
猴君
阅读量:1

前言:什么是跨域,网上一搜一大把,所以这里直接跳过,直入主题。

处理方式:不通过后端处理跨域,通过前端+服务器nginx处理。

1.前端涉及处理跨域的必要配置(开发环境、生产环境):vite3、vue3、axios

2.服务器涉及处理跨域的配置(生产环境):nginx【主要用到其配置文件nginx.conf】

3.配置开发环境【跟目录下分别创建:.env.development、.env.production】

        .env.development内容如下:

VITE_APP_PROXY_BASE_API='/proxyCustomerApi-dev'

        .env.production内容如下:

VITE_APP_PROXY_BASE_API='/proxyCustomerApi-pro'

     tips: .env.development、.env.production中的常量命名须以"VITE_"开头,这里定义的常量为VITE_APP_PROXY_BASE_API,值分别为"/proxyCustomerApi-dev"、"/proxyCustomerApi-pro"用以区分开发环境和生产环境,值可自定义为"/+自己想定义的内容"

4.前端vite.config.js中添加如下代码(代码中有相关注释):

import { defineConfig, loadEnv } from 'vite'; import vue from '@vitejs/plugin-vue'; import * as path from 'path'; ... ...  export default defineConfig((env) => {     // 获取到当前开发模式(dev/pro)下对应的环境文件对象值 	const evnMap = loadEnv(env.mode, process.cwd()); 	// console.log(`evnMap = ${JSON.stringify(evnMap)}`); 	return { 		... ... 		server: { 			host: '0.0.0.0', // ip地址 			port: 8088, // 启动端口 			// 反向代理配置,注意rewrite写法,开始没看文档在这里踩了坑 			proxy: { 				// 本地开发环境通过代理实现跨域,生产环境使用 nginx 转发 				// 对应项目根目录 - [.env.development、.env.production]文件中的值 				[evnMap.VITE_APP_PROXY_BASE_API]: { 					target: 'http://xxx.xx.xx.xx:27005', // 请求报跨域错误的接口域名地址,真实请求地址 					changeOrigin: true, // 支持跨域 					rewrite: (path) => 						path.replace(new RegExp('^' + evnMap.VITE_APP_PROXY_BASE_API), ''), // 重写真实路径,替换/api 					bypass: (req, res, options) => { 						const proxyUrl = options.target + options.rewrite(req.url); 						console.log(`真实请求的完整地址proxyUrl: ${proxyUrl}`); 					}, 				}, 			}, 		}, 	}; }); 

5.在自己封装好的axios js文件中修改下axios.create中的配置,代码如下:

const http = axios.create({ 	// baseURL: DOMAIN, 	// import.meta.env.VITE_APP_PROXY_BASE_API 对应项目根目录 - [.env.development、.env.production]文件中的值 	baseURL: import.meta.env.VITE_APP_PROXY_BASE_API, 	timeout: 600000,     ... ... });  export default http;

6.在自己出现跨域报错的接口处修改成类似如下代码片段:

export const chatHistoryRecordApi = { 	// 获取所有客服与用户对话列表 	getAllCustomerChatListPage: (params) => { 		return http({ 			// import.meta.env.VITE_APP_PROXY_BASE_API 对应项目根目录 - [.env.development、.env.production]文件中的值 			baseURL: import.meta.env.VITE_APP_PROXY_BASE_API, 			url: `/customer/allChatList`, 			method: 'get', 			params, 		}); 	}, 	// 查询指定对话的聊天历史记录 	queryCurrentChatHistory: (params) => { 		return http({ 			// import.meta.env.VITE_APP_PROXY_BASE_API 对应项目根目录 - [.env.development、.env.production]文件中的值 			baseURL: import.meta.env.VITE_APP_PROXY_BASE_API, 			url: `/customer/chatHistory`, 			method: 'get', 			params, 		}); 	}, };

至此前端跨域配置部分处理完成,可以调试开发环境【本地调试】了。

确保根目录下的package.json文件中存在scripts标签配置:

{ 	"name": "hrosass", 	"private": true, 	"version": "0.0.0", 	"type": "module", 	"scripts": {         // dev、build系统会默认添加--mode production/development环境配置         // "dev": "vite" =》"dev": "vite --mode development"         // "build": "vite build" =》"build": "vite build --mode production" 		"dev": "vite", 		"build": "vite build",         ... ... 	}, 	"dependencies": { 		... ... 	}, 	"devDependencies": { 		... ... 	}, 	"main": "index.js", 	... ... }

本地调试命令行中执行(我项目是用的yarn来运行):yarn run dev,发现接口可以请求拿到数据了。但在线上生产环境下还是会报错,如果只需要本地调试那到这里就完成了!!!

接下来处理生产环境(线上模式)下的跨域报错问题,由于刚刚前端的配置中已经加上了对生产环境的代理配置,其实也就是根目录下的这个文件【.env.production】。

7.本地连接上服务器,且服务器已配置好Nginx,找到Nginx的运行配置文件【nginx.conf】,内容大致如下(注意看注释):

# For more information on configuration, see: #   * Official English Documentation: http://nginx.org/en/docs/ #   * Official Russian Documentation: http://nginx.org/ru/docs/  user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid;   # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf;  events {     worker_connections 1024; }  http {     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                       '$status $body_bytes_sent "$http_referer" '                       '"$http_user_agent" "$http_x_forwarded_for"';      access_log  /var/log/nginx/access.log  main;      sendfile            on;     tcp_nopush          on;     tcp_nodelay         on;     keepalive_timeout   65;     types_hash_max_size 4096;     client_max_body_size 20M;      include             /etc/nginx/mime.types;     default_type        application/octet-stream;      # Load modular configuration files from the /etc/nginx/conf.d directory.     # See http://nginx.org/en/docs/ngx_core_module.html#include     # for more information.     include /etc/nginx/conf.d/*.conf;  		map $http_upgrade $connection_upgrade { 		default upgrade; 		'' close; 		}    # 加载vue前端项目的server   server {         listen       3004; # 端口         server_name  localhost; # 域名         location / {             root  /home/view/wallet/dist/; # 打包vue项目后的dist存放路径             index  index.html index.htm; # 加载入口html文件             try_files  $uri  $uri/  /index.html;         }         error_page   500 502 503 504  /50x.html;         location = /50x.html {             root   html;         }     }       # Settings for a TLS enabled server. # #    server { #        listen       443 ssl http2; #        listen       [::]:443 ssl http2; #        server_name  _; #        root         /usr/share/nginx/html; # #        ssl_certificate "/etc/pki/nginx/server.crt"; #        ssl_certificate_key "/etc/pki/nginx/private/server.key"; #        ssl_session_cache shared:SSL:1m; #        ssl_session_timeout  10m; #        ssl_ciphers PROFILE=SYSTEM; #        ssl_prefer_server_ciphers on; # #        # Load configuration files for the default server block. #        include /etc/nginx/default.d/*.conf; # #        error_page 404 /404.html; #            location = /40x.html { #        } # #        error_page 500 502 503 504 /50x.html; #            location = /50x.html { #        } #    }  }  

8.往server { location / { } }下边添加如下location反向代理配置(注意看注释):

# /proxyCustomerApi-pro为前端 .env.production中的指定的值 location /proxyCustomerApi-pro {             # 解决跨域             add_header 'Access-Control-Allow-Origin' '*' always;             add_header 'Access-Control-Allow-Credentials' 'true' always;             add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;             add_header 'Access-Control-Allow-Headers' 'Authorization,Refreshtoken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;             # 设置 options 请求处理             if ($request_method = 'OPTIONS') {                 add_header 'Access-Control-Allow-Origin' '*' always;                 add_header 'Access-Control-Max-Age' 1728000 always;                 add_header 'Content-Type' 'text/plain; charset=utf-8' always;                 add_header 'Content-Length' 0 always;                 # 对于Options方式的请求返回200或其它码,表示接受跨域请求                 return 200;             }             # 设置反向代理 http://://xxx.xx.xx.xx:27005不加/会拼上/proxyCustomerApi-pro 加/不会拼/proxyCustomerApi-pro 由于真实接口请求中没有/proxyCustomerApi-pro这段 这里不需要拼上 代理服务地址后应添加/   http://xxx.xx.xx.xx:27005/             proxy_pass http://://xxx.xx.xx.xx:27005/; # 后端API地址 引起跨域报错的api请求地址             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header Host $http_host;             proxy_set_header X-NginX-Proxy true;             proxy_http_version 1.1;             proxy_connect_timeout 600;             proxy_read_timeout 600;             proxy_send_timeout 600;             proxy_buffer_size 64k;             proxy_buffers 4 64k;             proxy_busy_buffers_size 128k;             proxy_temp_file_write_size 128k;             # 缓存时间,单位秒。这里设置的是6小时             expires 21600s;             # 收到304响应后,再次请求的时间间隔             proxy_cache_valid 200 304 12h;         }

9.配置后的nginx.conf完整内容如下:

# For more information on configuration, see: #   * Official English Documentation: http://nginx.org/en/docs/ #   * Official Russian Documentation: http://nginx.org/ru/docs/  user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid;   # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf;  events {     worker_connections 1024; }  http {     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                       '$status $body_bytes_sent "$http_referer" '                       '"$http_user_agent" "$http_x_forwarded_for"';      access_log  /var/log/nginx/access.log  main;      sendfile            on;     tcp_nopush          on;     tcp_nodelay         on;     keepalive_timeout   65;     types_hash_max_size 4096;     client_max_body_size 20M;      include             /etc/nginx/mime.types;     default_type        application/octet-stream;      # Load modular configuration files from the /etc/nginx/conf.d directory.     # See http://nginx.org/en/docs/ngx_core_module.html#include     # for more information.     include /etc/nginx/conf.d/*.conf;  		map $http_upgrade $connection_upgrade { 		default upgrade; 		'' close; 		}    # 加载vue前端项目的server   server {         listen       3004; # 端口         server_name  localhost; # 域名         location / {             root  /home/view/wallet/dist/; # 打包vue项目后的dist存放路径             index  index.html index.htm; # 加载入口html文件             try_files  $uri  $uri/  /index.html;         }         # /proxyCustomerApi-pro为前端 .env.production中的指定的值         location /proxyCustomerApi-pro {             # 解决跨域             add_header 'Access-Control-Allow-Origin' '*' always;             add_header 'Access-Control-Allow-Credentials' 'true' always;             add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;             add_header 'Access-Control-Allow-Headers' 'Authorization,Refreshtoken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;             # 设置 options 请求处理             if ($request_method = 'OPTIONS') {                 add_header 'Access-Control-Allow-Origin' '*' always;                 add_header 'Access-Control-Max-Age' 1728000 always;                 add_header 'Content-Type' 'text/plain; charset=utf-8' always;                 add_header 'Content-Length' 0 always;                 # 对于Options方式的请求返回200或其它码,表示接受跨域请求                 return 200;             }             # 设置反向代理 http://://xxx.xx.xx.xx:27005不加/会拼上/proxyCustomerApi-pro 加/不会拼/proxyCustomerApi-pro 由于真实接口请求中没有/proxyCustomerApi-pro这段 这里不需要拼上 代理服务地址后应添加/   http://xxx.xx.xx.xx:27005/             proxy_pass http://://xxx.xx.xx.xx:27005/; # 后端API地址 引起跨域报错的api请求地址             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header Host $http_host;             proxy_set_header X-NginX-Proxy true;             proxy_http_version 1.1;             proxy_connect_timeout 600;             proxy_read_timeout 600;             proxy_send_timeout 600;             proxy_buffer_size 64k;             proxy_buffers 4 64k;             proxy_busy_buffers_size 128k;             proxy_temp_file_write_size 128k;             # 缓存时间,单位秒。这里设置的是6小时             expires 21600s;             # 收到304响应后,再次请求的时间间隔             proxy_cache_valid 200 304 12h;         }         error_page   500 502 503 504  /50x.html;         location = /50x.html {             root   html;         }     }       # Settings for a TLS enabled server. # #    server { #        listen       443 ssl http2; #        listen       [::]:443 ssl http2; #        server_name  _; #        root         /usr/share/nginx/html; # #        ssl_certificate "/etc/pki/nginx/server.crt"; #        ssl_certificate_key "/etc/pki/nginx/private/server.key"; #        ssl_session_cache shared:SSL:1m; #        ssl_session_timeout  10m; #        ssl_ciphers PROFILE=SYSTEM; #        ssl_prefer_server_ciphers on; # #        # Load configuration files for the default server block. #        include /etc/nginx/default.d/*.conf; # #        error_page 404 /404.html; #            location = /40x.html { #        } # #        error_page 500 502 503 504 /50x.html; #            location = /50x.html { #        } #    }  }  

10.执行nginx命令【sudo service nginx reload】使配置生效,至此线上生产环境跨域配置完成。

调试线上跨域问题是否解决,前端项目执行:yarn run build打包线上版本生成dist文件夹并上传到服务器,刷新线上网址发现接口可以请求拿到数据了。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!