簡書原文css
自從先後端開發實現了愈來愈完全的分離,開發中遇到的跨域問題也隨之愈來愈多;
而不管是跨域請求JSONP,CORS或者window跨域window.name
,window.postMessage
,在實際開發使用中的表現都不夠完美。
相對來講 CORS 是官方的功能比較完善的方案,但除了須要服務器和瀏覽器雙方同時支持外,還有不少限制,好比Access-Control-Allow-Origin:*
不能發送cookie等,並且若是服務器設置不當也存在着一些安全隱患。html
固然,我寫這篇的重點不是吐槽,並且解決問題的。
更多關於跨域的資料請自行查閱,相關內容前端
《瀏覽器的同源策略》
《跨域資源共享 CORS 詳解》
《 深刻理解前端跨域方法和原理》angularjs
我並非一個前端開發,在以前的很長時間裏我都在作着後端開發的工做;
一個偶然的機會接觸到了angularJS的前端路由,當時我就想到了一個點子——作一個index.html
頁面,這個頁面只有一段js腳本,腳本的功能是將另一個存放於靜態存儲服務器的html頁面整個拉過來,寫到當前頁面中。web
好比我有一個服務器是這樣的:
api服務站點:www.xxx.com
靜態存儲服務:static.xxx.com
登陸頁面:static.xxx.com/20170420/login.html (中間的數字表示版本,下面會講到)
登陸接口:www.xxx.com/api/user/loginajax
很顯然,在登陸頁面調用登陸接口是一個跨域的行爲;
因此我如今在www.xxx.com中放一個index.html頁面
內容以下:後端
<script src="//static.xxx.com/config.js"></script> <script> (function (url) { if (/[?&]supportreload\b/i.test(location.search)) { window.loadPage = arguments.callee; } if (url) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); url += [(url.indexOf("?") < 0 ? "?" : "&"), "_", new Date().getTime()].join(""); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { var base = ['<base href="', url, '" />'].join(""); var html = xhr.responseText; html = html.replace(/(\<head[^>]*\>)/, "$1" + base); if (html === xhr.responseText) { html = base + html; } document.open(); document.write(html); document.close(); } else { document.write("'" + url + "' 加載失敗(" + xhr.statusText + ")..."); } } } xhr.open("GET", url, true); xhr.send(null); } })(window["index.page"]); </script>
其中引入了一個//static.xxx.com/config.js
,內容以下:api
window["index.page"] = "//static.xxx.com/20170420/login.html"
流程大體是這樣的
能夠看到,在index.html頁面被加載的同時,我引用了一個config.js,這個js也是存放在靜態資源服務器的,裏面聲明瞭一個參數window["index.page"]
,而index.html頁面會用這個變量中聲明的url拉取頁面,並write到當前頁面中。跨域
能夠看到導入的頁面是"//static.xxx.com/20170420/login.html",中間的數字能夠看作是版本,前端每次發佈均可以建立一個新的文件夾,保留以前的發佈內容,若是遇到問題須要回滾之類的操做,只須要將config.js
中的window["index.page"]
指向新的版本頁面便可;瀏覽器
另外頁面中的css,js等資源的問題,我在load page操做的時候會在頁面中加入<base >
標籤,保證大部分的相對引用資源都是沒問題的(js代碼中的地址不受base影響,如ajax);
爲了方便本地調試,特別加了這一段
if (/[?&]supportreload\b/i.test(location.search)) { window.loadPage = arguments.callee; }
當訪問 「www.xxx.com/index.html?supportreload」的時候,會註冊一個全局方法window.loadPage
,能夠load本地調試頁面,如:
window.loadPage("localhost:8080/login.html");
目前頁面跳轉有2個方案:
index.html
,如:config.Routes.MapHttpRoute( name: "webhtml", routeTemplate: "web/{*pattern}", defaults: new { controller = "webhtml", action = "index" } );
前端使用相對路徑的方式切換頁面,config.js
部分代碼作一些簡單的調整;
如:
window["index.page"] = "//static.xxx.com/20170420" + location.pathname
如今就能夠動態拉取頁面了,好比訪問
www.xxx.com/web/login.html的時候,會拉取並展現"//static.xxx.com/20170420/login.html"
www.xxx.com/web/user/manager/info.html的時候,會拉取並展現"//static.xxx.com/20170420/user/manager/info.html"