vue.config.js
。vue.config.js
里的配置项所有都是可选的,这就避免了我们去看一大堆不必要的默认配置,只需要配置自己需要的部分就行了。
首先,我们在vue.config.js文件中创建一个vueConfig 对象,并将其导出。
然后在vueConfig 对象里面再添加名为 devServer的key, 它的值也是一个对象。
const vueConfig = {
devServer: {
// development server port 8000
port: 8000,
// If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
proxy: {
'/login': {
target: process.env.VUE_APP_API_BASE_URL, // 需要代理的目标地址,一般是后端服务的ip:port。
ws: false, // 是否需要开启webSocket
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 设置为true, 本地就会虚拟一个服务器接收你的请求并代你发送该请求,这样就能跨域了
// 路径重写
pathRewrite: {
"^/login": '/api/v1/login' // authorize, 如果你的后边还有路径的
话, 会自动拼接上
} // 如: '^/login‘ :表示 接口中的/login 会被替换成 /api/v1/login。 然后再加上target,完整的地址应该把是: ip:port/api/v1/login。
},
'/oauth': {
target: process.env.VUE_APP_API_BASE_URL,
ws: false,
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true,
// 路径重写
pathRewrite: {
"^/oauth": '/oauth' // 如果你的后边还有路径的话, 会自动拼接上
},
}
}
},
}
里面其他的选项我们暂时不讲,着重讲代理的部分,也就是proxy。
proxy里一对key-value就是对一个后端地址的代理。
一般我们一个项目工程你可以建立四个环境变量文件:
.env文件:全局默认配置文件,不论什么环境都会加载合并
.env.development文件:开发环境下的配置文件
.env.production文件:生产环境下的配置文件
.evn.preview文件:生产环境预览下的配置文件,这个环境用的比较少
.env文件会根据你是开发环境还是生产环境来合并对应的变量。
所有环境变量文件内的属性名必须以VUE_APP_开头,比如VUE_APP_XXX
vue-cli会根据启动命令自动加载对应的环境,vue是根据文件名进行加载的,所以上面说“不要乱起名,也无需专门控制加载哪个文件”
比如执行npm run serve命令,会自动加载.env.development文件。npm run build会自动加载.env.production文件。
const service = axios.create({
baseURL: (process.env.NODE_ENV === 'production' && baseConfig.gateway) ? process.env.VUE_APP_API_BASE_URL : '', // api base_url
timeout: 20000, // 请求超时时间
withCredentials: false
})
我们在创建axios时,其中有一个baseURL的配置项,这个配置项可以直接理解为是http请求地址的前缀。
其他配置:
const baseUrlPrefix = '/api/v1' // 除了baseURL外的通配前缀
const gateway = false // 是否走网关代理
了解了上面几个基础知识和配置,下面我们分三种环境来配置我们的跨域代理。
开发环境时,跨域代理直接在vue.config.js中配置即可,target直接使用.env.development中配置的baseUrl就行
NODE_ENV=development
VUE_APP_PREVIEW=true
VUE_APP_API_BASE_URL='http://ip:port'
注意,此时target已经配置了baseUrl,也就是前缀已经有了,axios实例中的baseURL就不需要配置了,直接填空‘’就行。
此时axios请求实例为:
const systemRole = `${baseConfig.gateway ? baseConfig.baseUrlPrefix : ''}/authorize/systemRole`,
export function getSystemRoleList (parameter) {
return axios({
url: `${systemRole}s`,
method: 'get',
params: parameter
})
}
其中/authorize会被devServer中配置的
pathRewrite: {
"^/authorize": '/api/v1/authorize' // authorize, 如果你的后边还有路径的话, 会自动拼接上
}
中的'/api/v1/authorize'自动替换。
所以最终的请求url为:
http://ip:port/api/v1/authorize/systemRoles
由于vue.config.js中只能配置devServer,所以生产环境的代理并不能在此配置,所以我们一般生产环境都会打包部署到nginx服务器或者其他的代理服务器,这里以nginx代理举例。
同样,如果是nginx代理,axios实例依然不需要配置baseURL:
const service = axios.create({
baseURL: (process.env.NODE_ENV === 'production' && baseConfig.gateway) ? process.env.VUE_APP_API_BASE_URL : '', // api base_url
timeout: 20000, // 请求超时时间
withCredentials: false
})
上面的 baseConfig.gateway表示走网关,nginx代理时,该值为false。
axios请求也一样,gateway为false时,url除了baseURL只需要带上‘/authorize’这条通用协议和后面的业务地址。
const systemRole = `${baseConfig.gateway ? baseConfig.baseUrlPrefix : ''}/authorize/systemRole`,
export function getSystemRoleList (parameter) {
return axios({
url: `${systemRole}s`,
method: 'get',
params: parameter
})
}
nginx配置:
#user nobody;
worker_processes 4;
error_log /usr/local/nginx/logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid /program/nginx/nginx.pid;
events {
use epoll;
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
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 /usr/local/nginx/logs/access.log main;
client_max_body_size 20M;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#request的header中包含’_’时,不忽略
underscores_in_headers on;
gzip on;
gzip_static on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "msie6"; #不使用gzip IE6
gzip_min_length 1024; #gzip压缩最小文件大小,超出进行压缩(自行调节)
gzip_buffers 4 16k; #buffer 不用修改
gzip_comp_level 3; #压缩级别:1-10,数字越大压缩的越好,时间也越长
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; # 压缩文件类型
gzip_vary off; #跟Squid等缓存服务有关,on的话会在Header里增加 "Vary: Accept-Encoding"
upstream authorize_{
ip_hash;
server 127.0.0.1:81;
}
upstream oauth_{
ip_hash;
server 127.0.0.1:88;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /program/www/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /authorize{
proxy_pass http://authorize_/api/v1/authorize;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /oauth{
proxy_pass http://oauth_/oauth;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
很明显,nginx的配置和devServer的配置其实是一样的,所以可以理解为生产环境中nginx帮助做了开发环境devServer做的事情。
最终,请求的地址依然是:
http://ip:port/api/v1/authorize/systemRoles
最后,如果生产环境不走nginx代理,而是用网关统一代理,那么我们这里devServer和nginx都不需要配置了。
直接把完整的请求地址传给网关服务器,剩下的工作交给网关自己来处理。
此时,gateway配置需要修改:
const baseUrlPrefix = '/api/v1'
const gateway = true
axios实例:
// 创建 axios 实例
const service = axios.create({
baseURL: (process.env.NODE_ENV === 'production' && baseConfig.gateway) ? process.env.VUE_APP_API_BASE_URL : '', // api base_url
timeout: 20000, // 请求超时时间
withCredentials: false
})
baseURL此时需要配置网关服务器指定的地址.env.production:
NODE_ENV=production
VUE_APP_PREVIEW=false
VUE_APP_API_BASE_URL='http://gatewayAddress:port/XXX'
axios请求方法:
const systemRole = `${baseConfig.gateway ? baseConfig.baseUrlPrefix : ''}/authorize/systemRole`,
export function getSystemRoleList (parameter) {
return axios({
url: `${systemRole}s`,
method: 'get',
params: parameter
})
}
此时由于gateway为true,所以需要在baseURL前面添加baseUrlPrefix :'/api/v1'
最后,axion请求的真实地址为:
http://gatewayAddress:port/api/v1/authorize/systemRoles
网关服务那边会识别这个地址,然后配置到你需要请求的真实的的地址上去。
以上就是三种环境或者代理模式下的跨域代理方式。
——end
欢迎留言交流。