window.requestAnimationFrame()
的最低兼容 ie 版本為 10,那么在 ie9 上做兼容就需要制作 requestAnimationFrame polyfill
(function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }());
Gist:requestAnimationFrame polyfill
這部分代碼同樣是盡可能在網(wǎng)站入口處就執(zhí)行
http網(wǎng)絡(luò)請求(跨域)
在大多數(shù)的 Web 項目中(以 JavaWeb 為例),網(wǎng)站的頁面和服務(wù)(至少是 controller 層)在同一個工程進(jìn)行開發(fā)和部署,在大前端的新型模式下,我們建議盡可能對網(wǎng)站的前端和后端進(jìn)行完全分離,前后端分離的好處和意義這里不再贅述。
既然是前后端分離,那么部署也必然是各自獨立部署,不同的訪問路徑,就會產(chǎn)生跨域訪問的問題(同一站點,不同端口號也是跨域)
在此設(shè)定背景情況:
高版本瀏覽器(ie10+ 或 chrome, ff)僅需要完成背景情況中的功能,即可支持跨域數(shù)據(jù)請求功能
axios 進(jìn)行數(shù)據(jù)請求時,默認(rèn)使用 XMLHttpRequest 對象,在檢測到當(dāng)前請求是跨域訪問時,axios 會測試瀏覽器是否支持 XDomainRequest 對象,若支持則優(yōu)先使用。
ie8 / ie9 的 XMLHttpRequest 對象,不支持跨域訪問,該對象在 ie10 后才原生支持跨域訪問。微軟的解決方案是在 ie8 / ie9 中提供了XDomainRequest(XDR) 對象來進(jìn)行解決跨域問題,雖然使用該對象可以跨域訪問成功,并返回數(shù)據(jù),但它卻依然是一個功能不完整的半成品,它的使用有諸多限制:
微軟雖然提供了解決方案,但卻是不折不扣的雞肋,根本無法勝任系統(tǒng)中各種場景的數(shù)據(jù)請求需求,至此,axios 對 ie9 的跨域數(shù)據(jù)請求已無能為力。
完美解決方案:代理(proxy)
雖然 axios 對 ie9 跨域已無能為力,但前端項目打包的解決方案 webpack 提供了一個優(yōu)雅而徹底解決問題的方式:代理
devServer.proxy
webpack 的 devServer.proxy
的功能是由http-proxy-middleware 項目來實現(xiàn)的
實現(xiàn)原理是將目標(biāo)位置的請求代理為前端服務(wù)本地的請求,既然是代理成為本地的請求,就不存在跨域的問題,axios 就會用回 XMLHttpRequest
對象進(jìn)行數(shù)據(jù)請求,一切都恢復(fù)正常了,header、cookies、content-type、authentication 等內(nèi)容都被正確傳遞到服務(wù)端。
項目中 webpack.config.js 的配置
devServer: { historyApiFallback: true, noInfo: true, overlay: true, proxy: { '/api': { target: 'http://localhost:8081/myserver', pathRewrite: { '^/api': '' } } } }
配置中指定了將 http://localhost:8081/myserver 服務(wù)的位置代理為本地前端服務(wù)的 http://localhost:8080/api。例如需要讀取用戶信息的原請求是 http://localhost:8081/myserver/user/zhangsan,代理后,就變?yōu)?http://localhost:8080/api/user/zhangsan。
即是 /api 的前綴代表了服務(wù)端,所以在使用 axios 時,需要對每個服務(wù)端請求都增加上 /api 的前綴;通常在項目開發(fā)中,需要對數(shù)據(jù)請求組件 axios 進(jìn)行二次封裝,以達(dá)到統(tǒng)一設(shè)置默認(rèn)參數(shù),統(tǒng)一數(shù)據(jù)請求入口等目的,那么此時就只需要在二次封裝的文件里統(tǒng)一調(diào)整請求前綴即可。
不過,webpack 的 devServer.proxy
僅在開發(fā)模式下可用,生產(chǎn)模式下無法使用。開發(fā)模式下,調(diào)試服務(wù)可以讀取 webpack.config.js
中的配置內(nèi)容進(jìn)行實時代理,而項目在部署到生產(chǎn)環(huán)境前,需要將工程進(jìn)行編譯轉(zhuǎn)換成靜態(tài)的 js 文件,沒有調(diào)試服務(wù)的支撐自然是無法進(jìn)行請求代理的。
nginx 配置
雖然 devServer.proxy
的功能僅能工作于開發(fā)模式,那么在生產(chǎn)模式下,自然也是有解決方案的;通常 Vue 的項目在編譯成最終的 js 文件后,僅需要靜態(tài)服務(wù)器即可,這其中又以 nginx 為最優(yōu)選擇方案,輕量、高性能、高并發(fā)、反向代理服務(wù)等均為其優(yōu)點,這里需要做的數(shù)據(jù)請求代理的功能就使用到了 nginx 的 反向代理 功能
conf/nginx.conf
文件配置增加以下內(nèi)容
location /api/ { proxy_pass http://localhost:8081/myserver/; }
該配置同樣是將 http://localhost:8081/myserver/ 的目標(biāo)服務(wù)端位置代理為本地服務(wù)的 /api 路徑,如此,生產(chǎn)環(huán)境下的數(shù)據(jù)請求問題也得以解決
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com