vue-cli3 多環境和多後端的跨域代理配置 多種實現方案

大家都知道,由於3.x的默認配置都轉移到了CLI service,所以生成的項目中並沒有默認配置文件,所以我們如果需要自定義一些項目配置,則需要自己在項目的根目錄創建一個vue.config.js

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文件。

 

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
})

我們在創建axios時,其中有一個baseURL的配置項,這個配置項可以直接理解爲是http請求地址的前綴。

 

其他配置:

const baseUrlPrefix = '/api/v1' // 除了baseURL外的通配前綴
const gateway = false // 是否走網關代理

 

瞭解了上面幾個基礎知識和配置,下面我們分三種環境來配置我們的跨域代理。

1. 本地開發環境:

開發環境時,跨域代理直接在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

 

2. 生產環境通過nginx代理:

由於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

3. 生產環境通過網關代理:

最後,如果生產環境不走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

歡迎留言交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章