前言:什么是跨域,網上一搜一大把,所以這里直接跳過,直入主題。
處理方式:不通過后端處理跨域,通過前端+服務器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), ''), // 重寫真實路徑,替換/apibypass: (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前端項目的serverserver {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前端項目的serverserver {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文件夾并上傳到服務器,刷新線上網址發現接口可以請求拿到數據了。