第一部:避坑前期
今天打算將本地vue項(xiàng)目打包到服務(wù)器nginx部署,部署后發(fā)現(xiàn)不能請(qǐng)求到數(shù)據(jù),提示跨域問(wèn)題

但是我看別人一本正經(jīng)的說(shuō)前臺(tái)和后臺(tái)部署在同一臺(tái)服務(wù)器不存在跨域問(wèn)題,是這樣嗎?
我本地啟動(dòng)前后端一起調(diào)試時(shí)也有跨域問(wèn)題啊,它們也是在我這一臺(tái)電腦上的啊,但我的理解是IDE運(yùn)行前端項(xiàng)目時(shí)會(huì)依賴node幫我們構(gòu)建一個(gè)虛擬服務(wù)器,那么這個(gè)運(yùn)行前端項(xiàng)目的虛擬服務(wù)器就和我的本地運(yùn)行后端程序的Tomcat是兩個(gè)獨(dú)立的服務(wù)器,這樣就存在跨域了。
那么怎么解決呢,我是通過(guò)設(shè)置開(kāi)放后端允許跨域的相關(guān)配置來(lái)解決的,這樣前端就可以訪問(wèn)了,就是postman訪問(wèn)的路徑,交給axios相同的路徑就能訪問(wèn)成功。但就是部署到nginx就不行,于是找解決辦法,有的說(shuō)要配置代理,那就試試看
第二部:配置代理
突然心生一問(wèn),如果配置好代理后是不是就不用了在后端進(jìn)行跨域設(shè)置了,就像起初用postman或者瀏覽器都可以訪問(wèn),大家有空可以驗(yàn)證一下,我覺(jué)得是這樣的,因?yàn)槎颊f(shuō)代理能解決跨域。
我們先還是配置代理吧,以下是我的環(huán)境

項(xiàng)目結(jié)構(gòu)是這樣的,vue.config.js是自己手動(dòng)添加的

代理主要是在vue.config.js中完成配置,我把配置內(nèi)容貼出來(lái),核心就是proxy節(jié)點(diǎn)的內(nèi)容
const url = 'http://localhost:8088'
module.exports = {
// webpack-dev-server配置
devServer: {
open: false, //編譯完是否自動(dòng)打開(kāi)網(wǎng)頁(yè)
host: '0.0.0.0', //指定使用地址,默認(rèn)localhost,0.0.0.0代表可以被外界訪問(wèn)
port: 8080, // web網(wǎng)頁(yè)端口號(hào)
https: false,//編譯失敗時(shí)刷新頁(yè)面
hot: true, //開(kāi)啟熱加載
hotOnly: false,
//設(shè)置代理
// 配置不同的后臺(tái)API地址
proxy: {
'/devApi': {
target: url,
ws: false,
changeOrigin: true, //支持跨域
pathRewrite: {
'^/devApi': ''
},
'/devApi-1': { //這個(gè)是我為了說(shuō)明多加的,我項(xiàng)目中是沒(méi)有的
target: url,
ws: false,
changeOrigin: true, //支持跨域
pathRewrite: {
'^/devApi-1': ''
}
}
},
overlay: {//全屏模式下是否顯示腳本錯(cuò)誤
warning: true,
errors: true
},
before: app => {
}
}
}
代理可以配置多個(gè),不同的名稱方便管理,配置多個(gè)有什么用?假如你有多個(gè)后臺(tái)微服務(wù)接口,這些服務(wù)都部署在不同機(jī)器上,那么你就需要對(duì)每一個(gè)微服務(wù)進(jìn)行配置代理。
我們?cè)倏纯碼xios是怎么配置的,只貼出httpRequest.js關(guān)鍵部分
import axios from 'axios'
const BASEURL = process.env.NODE_ENV === 'production' ? '/appApi' : '/devApi'
const http = axios.create({
// baseURL: BASEURL,
timeout: 1000 * 30,
withCredentials: true,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
})
/**
* 請(qǐng)求地址處理
* @param {*} actionName action方法名稱
*/
http.adornUrl = (actionName) => {
// 非生產(chǎn)環(huán)境 && 開(kāi)啟代理, 接口前綴統(tǒng)一使用[/devApi/]前綴做代理攔截!
return BASEURL+actionName
}
這一句能看懂吧process.env.NODE_ENV,就是只要項(xiàng)目本地運(yùn)行起來(lái)它的值就是development,但要是打包成dist之后在服務(wù)器上運(yùn)行時(shí)它的值就是production,你可能問(wèn)這個(gè)只是哪來(lái)的,我只能告訴你這應(yīng)該是vue-cli框架規(guī)定的吧,具體參考以下(有點(diǎn)像我上篇springboot多環(huán)境配置,maven打包時(shí)可以選環(huán)境)

總之本地運(yùn)行時(shí)它是不會(huì)等于production的,所以它的值是BASEURL = '/devApi'
然后注意這個(gè)http.adornUrl,頁(yè)面發(fā)起請(qǐng)求會(huì)先調(diào)用該屬性進(jìn)行拼接請(qǐng)求url,會(huì)傳遞過(guò)來(lái)一個(gè)actionName,比如actionName='/abc/login',那么他會(huì)返回一個(gè)'/devApi/abc/login'
然后發(fā)起請(qǐng)求,那么此時(shí)就會(huì)根據(jù)'/devApi'去找對(duì)應(yīng)的代理配置,找到后會(huì)替換成'http://localhost:8088/devApi/abc/login',我們看到這玩兒意也不對(duì)啊肯定請(qǐng)求不到報(bào)404,然后pathRewrite出場(chǎng)了把'/devApi'給它替換成' '空串,就得到了'http://localhost:8088/abc/login'完成訪問(wèn)
注意:
1.baseURL: BASEURL,如果這里配置了baseURL='/devApi',那么頁(yè)面就不要調(diào)用http.adornUrl添加拼接url了,直接給出'/abc/login'發(fā)起請(qǐng)求就可以了
2.這樣看下來(lái)這里代理的配置,只對(duì)本地跨域有用,如果不跨域我也用不著,但是有個(gè)好處就是他把我們發(fā)起的每個(gè)http真是請(qǐng)求路徑給隱藏了,變成下面http://localhost:8080/devApi/.......,要知道我們不采用代理時(shí)這里看到的請(qǐng)求就是我們真實(shí)的請(qǐng)求api接口路徑。

3.部署生產(chǎn)環(huán)境到nginx的時(shí)候,nginx的代理你是必須配置的,但是跟本地的這個(gè)配置文件內(nèi)容是沒(méi)有關(guān)系的,配置方式也不一樣,但是生產(chǎn)環(huán)境BASEURL = '/appApi' 這個(gè)要和nginx的配置對(duì)應(yīng),以下是nginx配置文件路徑/usr/local/devtool/nginx-1.6.3/conf/nginx.config
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /home/vue-demo/dist/; #項(xiàng)目打包存放路徑
index index.html index.htm;
}
location /appApi {
rewrite ^.+appApi/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://172.27.88.154:8088; #后端服務(wù)地址
#關(guān)鍵部分start
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token';
#關(guān)鍵部分end
#以下配置參見(jiàn)nginx配置文檔哈
#Proxy Settings
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection close;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_max_temp_file_size 0;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
內(nèi)容較多,這里只貼部分,復(fù)制時(shí)注意括號(hào)閉合,核心配置是'/appApi'要和項(xiàng)目中設(shè)置的值一致,至于后面的配置按需添加即可,修改保存后,執(zhí)行以下命令讓文件載入生效,同時(shí)注意該文件注釋內(nèi)容不能用// 要用#注釋?zhuān)駝t啟動(dòng)nginx報(bào)錯(cuò)
./nginx -s reload
我沒(méi)有配置環(huán)境變量,所以該命令在nginx安裝目錄sbin下執(zhí)行,具體看nginx操作命令即可

至此生產(chǎn)環(huán)境部署成功
另外給出個(gè)連接,算是能把這塊講的還算清楚的
https://www.bilibili.com/video/BV1vJ411E7rn?p=20