前言
最近做的一個項目中使用了vue+springboot的前后端分離模式
在前端開發的的時候,使用vue cli3的devServer來解決跨域問題
上線部署則是用的nginx反向代理至后台服務所開的端口
正文
開發環境中的跨域
首先,要確定后台服務的ip與端口
這里我的后台開的是
localhost:8081
npm run serve在8080
端口
一般我們使用ajax請求的時候,會可以把url ip:port/api
寫在ajax請求的url參數中
this.axios.get("localhost:8081"+ `/bpi/api/DayTradeinfoMarketStatusSearch?ddate=${day}`)
這樣,這個請求就是從localhost:8080發向localhost:8081,端口不同這就遇到了跨域的問題
vue cli WebpackDevServer 解決跨域的方法是通過node開一個服務器進行代理。
前台發向后台服務器的請求,先發向node所開的服務,node服務器以相同的參數向真正的服務器進行請求,再把響應返回給前台。
禁止跨域是瀏覽器的安全策略限制
這里有兩個誤區
- ✕ 動態請求就會有跨域的問題
✔ 跨域只存在於瀏覽器端,不存在於安卓/ios/Node.js/python/ java等其它環境
2.✕ 跨域就是請求發不出去了
✔ 跨域請求能發出去,服務端能收到請求並正常返回結果,只是結果被瀏覽器攔截了
詳情請看
我知道的跨域與安全-李銀成
在vue cli3中的配置
在package.json同級目錄下新建vue.config.js文件
//vue.config.js
module.exports = {
devServer: {
proxy: {
'/bpi': { // 以'/bpi'開頭的請求會被代理進行轉發
target: 'http://localhost:8081', // 要發向的后台服務器地址 如果后台服務跑在后台開發人員的機器上,就寫成 `http://ip:port` 如 `http:192.168.12.213:8081` ip為后台服務器的ip
changeOrigin: true
}
}
}
}
ajax請求的寫法
this.axios.get(`/bpi/api/DayTradeinfoMarketStatusSearch?ddate=${day}`) //相比上面的寫法,這里吧ip和端口去掉了,這樣所發的請求會自動補全為 `localhost:port/api` (port是npm run serve所開的端口)
這樣,如果打開瀏覽器調試工具的network會發現請求依然發向 localhost:8080而不是后台服務的端口8081
但是沒得關系,node已經幫你向8081端口請求了數據~
上線的時候使用nginx進行部署
使用npm run build命令打包,得到dist文件夾里面的內容就是靜態文件,使用任何一個服務器返回里面的index.html就能在瀏覽器看到頁面。
要注意服務器映射的目錄和vue build的時候的路徑配置
即vue.comfig.js里的 publicPath配置項
//vue.config.js
module.exports = {
publicPath:'./', //可以理解成build出來的index.html從哪里找他引用的js、css等文件。默認是"/"從根目錄尋找
devServer: {
hotOnly:true,
disableHostCheck:true,
proxy: {
'/bpi': {
target: 'http://localhost:8081',
// ws: true,
// port:8083
changeOrigin: true
}
}
},
}
publicPath配置為"./" 時:
<script src=js/chunk-vendors.9049ec28.js></script><script src=js/app.379ce736.js></script>
publicPath配置為"/" 時:
<script src=/js/chunk-vendors.9049ec28.js></script><script src=js/app.379ce736.js></script>
nginx的配置
把dist中的內容放到nginx安裝目錄下的html文件夾里(也可以在conf文件夾的nginx.conf中修改要映射的文件夾)
打開nginx.conf
#nginx.conf
#只貼了一些重要內容上來,其他的配置保持默認就好
http {
server {
listen 8082; //監聽的端口
server_name localhost;
location / { // 表示 以'/'開頭的請求怎樣處理
root html; //指定root文件夾為 上面提到的html文件夾
index index.html; //返回index.html
}
location /bpi{ // 表示 以'/bpi'開頭的請求 怎樣處理
proxy_pass http://localhost:8081; //以同樣的蠶食向這個地址請求,並返回給客戶端
}
}
}
這樣,我們訪問localhost:8082的時候,就會把index.html文件返回
雖然network顯示接口是發現8082的,但是會反向代理到8081,這樣就從后台服務器拿到了數據~~~~
vue部署的時候還剩下一個問題
由於vue開發的是單頁面應用(可以看到,一般情況下build出來的dist文件夾里面只有一個html文件)
雖然我們通過vue-router可以實現各種路由,但是在部署之后,頁面一刷新就會碰到404錯誤
這是由於 如果刷新之前 的路由是localhost:8082/bookList/detail
,這樣的話刷新之后向服務器請求的是root文件夾下的bookList文件夾下的detail,而不是根目錄中的index.html了,這就需要做一點小處理
#error_page 404 /index.html; //404的時候就返回index.html
#nginx.conf
#只貼了一些重要內容上來,其他的配置保持默認就好
http {
server {
listen 8082; //監聽的端口
server_name localhost;
location / { // 表示 以'/'開頭的請求怎樣處理
root html; //指定root文件夾為 上面提到的html文件夾
index index.html; //返回index.html
}
location /bpi{ // 表示 以'/bpi'開頭的請求 怎樣處理
proxy_pass http://localhost:8081; //以同樣的蠶食向這個地址請求,並返回給客戶端
}
error_page 404 /index.html; //404的時候就返回index.html
}
}
404的時候就返回index.html
這樣進入到index.html后,vue-router再根據地址欄的地址,來決定渲染什么模板,如此一來任性的甲方再怎么刷新也不會報404啦~~