最近實(shí)驗(yàn)課上需要重構(gòu)以前寫過(guò)的一個(gè)項(xiàng)目(垃圾堆)晨汹,需要添加發(fā)生郵件提醒的功能镜撩,記得以前寫過(guò)一個(gè)PHP版的實(shí)現(xiàn)旧巾,所以想把PHP寫的功能整理成一個(gè)服務(wù),然后在前端調(diào)用蜕劝。但是這個(gè)項(xiàng)目是JavaWeb檀头,也就是說(shuō)我需要面對(duì)跨域的問(wèn)題。不過(guò)本篇文章熙宇,講的并不是如何解決這樣的跨域問(wèn)題鳖擒,而是我在找如何解決這個(gè)問(wèn)題的路上遇到的坑溉浙。
其實(shí)烫止,在前端工程化大行其道的現(xiàn)在,前后端已經(jīng)分離開(kāi)來(lái)戳稽,前端為了提高工作流效率往往自己開(kāi)一個(gè)小型的服務(wù)器馆蠕,就比如webpack.devServer期升。這樣在前端調(diào)用后端接口的時(shí)候必然會(huì)面臨跨域的問(wèn)題,
如題互躬,Vue3.x + axios 跨域方案 就是解決這里的跨域問(wèn)題播赁。這里的跨域是基于webpack的devServer的代理功能(proxy)來(lái)實(shí)現(xiàn)開(kāi)發(fā)環(huán)境中的跨域,也就是說(shuō)本篇所討論的并不能解決生產(chǎn)環(huán)境下的跨域問(wèn)題吼渡,因?yàn)閣ebpack.devServer是DevDependencies容为,一旦打包上線,這個(gè)proxy代理就會(huì)失效寺酪。但是這并不妨礙我們開(kāi)發(fā)中使用跨域來(lái)提高開(kāi)發(fā)效率和體驗(yàn)坎背。
開(kāi)始填坑
其實(shí)這個(gè)問(wèn)題解決起來(lái)很簡(jiǎn)單,網(wǎng)上也是很多教程寄雀,為了文章完整性得滤,我這里也做一個(gè)盡量完備的展示,介紹如何配置Vue3.x來(lái)實(shí)現(xiàn)跨域 盒犹。
vue.config.js中devServer.proxy的配置解析
Vue3.x的CLI工具比Vue2.x的CLI工具構(gòu)建的項(xiàng)目要簡(jiǎn)化很多懂更,根目錄下只有./src和./public文件夾泣栈,所以網(wǎng)上很多教程說(shuō)config目錄下的vue.config.js是說(shuō)的vue2.x版本维贺。那么對(duì)于Vue3.x版本茎芭,構(gòu)建也很簡(jiǎn)單雀鹃,直接在根目錄里建一個(gè)vue.config.js配置文件就可以了拣帽,我們直接看devServer.proxy里的代碼:
我這里devServer的地址是:localhost:8080/烫葬,需要代理的地址是:localhost/index/phpinfo.php (我自己寫的一個(gè)測(cè)試跨域用的php荷辕,返回一個(gè)‘ok')
下面是根據(jù)上面的地址需要配置的proxy對(duì)象
devServer : {
proxy : {
'/index' : {
target : 'http://localhost/index',
// ws : true,
changeOrigin : true,
pathRewrite : {
'^/index' : ''
}
}
}
}
大部分教程到這里就停止了昧甘,但是我在這里做一個(gè)擴(kuò)展命黔,為了讓讀者理解這里的配置是如何起作用的(以下內(nèi)容整理自http-proxy-middleware的npm描述里呜呐,http-proxy-middleware是一個(gè)npm模塊,是proxy的底層原理實(shí)現(xiàn))悍募。
foo://example.com:8042/over/there?name=ferret#nose
\_/?? \______________/\_________/ \_________/ \__/
|?????????? |??????????? |??????????? |??????? |
scheme???? authority?????? path??????? query?? fragment
以我上面的配置為例蘑辑,'/index'這個(gè)key在http-proxy-middleware中被稱為context――用來(lái)決定哪些請(qǐng)求需要被target對(duì)應(yīng)的主機(jī)地址(這里是http://localhost/index)代理,它可以是 字符串坠宴,含有通配符的字符串洋魂,或是一個(gè)數(shù)組,分別對(duì)應(yīng)于path matching(路徑匹配)wildcard path matching(通配符路徑匹配)multiple path matching(多路徑匹配)喜鼓,而這里的path指的就是上圖所標(biāo)識(shí)的path段副砍。
簡(jiǎn)言之,這個(gè)key就是匹配path的庄岖,一旦匹配到符合的path豁翎,就會(huì)把請(qǐng)求轉(zhuǎn)發(fā)的代理主機(jī)去,而代理主機(jī)的地址就是target字段對(duì)應(yīng)的內(nèi)容隅忿。
那pathRewrit是什么意思呢心剥?意如其名邦尊,路徑重寫。就是把模式(這里是^/index)匹配到的path重寫為對(duì)應(yīng)的路徑(這里是''优烧,相當(dāng)于刪除了這個(gè)匹配到的路徑)蝉揍。除了刪除,還有在原有路徑上添加一個(gè)基礎(chǔ)路徑畦娄,或是改寫一個(gè)路徑的方式又沾,這可以參考http-proxy-middleware的npm描述的option.pathRewrite章節(jié)?。
在Vue中使用axios
這個(gè)使用任意一個(gè)ajax封裝的庫(kù)都是可行的熙卡,axios捍掺,jquery.ajax或者是vue-resource都是可以的。
在Vue中使用axios再膳,網(wǎng)上有兩種方法挺勿,一種是將axios加入Vue的原型里,我更推薦第二種方法:
npm install axios vue-axios
import axios from 'axios';
import VueAxios from 'vue-axios';
Vue.use(VueAxios,axios);
以我上面的proxy配置為基礎(chǔ)喂柒,想要讓代理成功轉(zhuǎn)發(fā)到localhost/index/phpinfo.php不瓶,在Vue實(shí)例中axios需要這樣寫訪問(wèn)地址:
this.axios.get('/index/phpinfo.php').then((res)=>{
console.log(res);
})
我們來(lái)分析這些代碼整個(gè)發(fā)揮作用的原理是什么?首先灾杰,axios去訪問(wèn)/index/phpinfo.php蚊丐,這是個(gè)相對(duì)地址,所以真實(shí)訪問(wèn)地址其實(shí)是localhost:8080/index/phpinfo.php艳吠,然而/index/phpinfo.php被我們配置的/index匹配到了 麦备,所以訪問(wèn)被proxy代理,那轉(zhuǎn)發(fā)到哪個(gè)路徑呢昭娩?在pathRewrite中凛篙,我們將模式^/index的路徑清除了,所以最終的訪問(wèn)路徑是 target+pathRewrite+ 剩余的部分 栏渺, 這樣也就是 http://localhost/index++/phpinfo.php
坑點(diǎn)
可能出現(xiàn)即使配置了proxy呛梆,但是依然沒(méi)有任何卵用。
大部分情況是因?yàn)槟愕膒roxy配置和你的訪問(wèn)路徑不匹配磕诊,或者即使匹配到了填物,但是轉(zhuǎn)發(fā)出去的地址不對(duì),沒(méi)有命中后端給的API
或者看看axios霎终,有沒(méi)有使用正確姿勢(shì)滞磺?
還有一點(diǎn),或許你看到返回的response里的url依然顯示的是本地主機(jī)莱褒,但是數(shù)據(jù)已經(jīng)正常返回击困,這是正常的,因?yàn)槲覀冊(cè)L問(wèn)的本來(lái)就是本地主機(jī)保礼,只不過(guò)proxy轉(zhuǎn)發(fā)了這個(gè)請(qǐng)求到一個(gè)新的地址沛励。
后續(xù)
本篇只解決了開(kāi)發(fā)環(huán)境下的跨域問(wèn)題,實(shí)際線上還不能跨域炮障,目前這里有一些方案:
Nginx反向代理跨域
JSONP
CORS
文章同步發(fā)布:?https://www.geek-share.com/detail/2783995081.html
參考文章: