原文出處: 小鬍子哥的部落格(@Barret李靖)
前後端分工協作是一個老生常談的大話題,很多公司都在嘗試用工程化的方式去提升前後端之間交流的效率,降低溝通成本,並且也開發了大量的工具。但是幾乎沒有一種方式是令雙方都很滿意的。事實上,也不可能讓所有人都滿意。根本原因還是前後端之間的交集不夠大,交流的核心往往只限於介面及介面往外擴散的一部分。這也是為什麼很多公司在招聘的時候希望前端人員熟練掌握一門後臺語言,後端同學瞭解前端的相關知識。
一、開發流程
前端切完圖,處理好介面資訊,接著就是把靜態demo交給後臺去拼接,這是一般的流程。這種流程存在很多的缺陷。
後端同學對檔案進行拆分拼接的時候,由於對前端知識不熟悉,可能會搞出一堆bug,到最後又需要前端同學幫助分析原因,而前端同學又不是特別瞭解後端使用的模板,造成尷尬的局面。
如果前端沒有使用統一化的資料夾結構,並且靜態資源(如圖片,css,js等)沒有剝離出來放到 CDN,而是使用相對路徑去引用,當後端同學需要對靜態資源作相關配置時,又得修改各個link,script標籤的src屬性,容易出錯。
介面問題
後端資料沒有準備好,前端需要自己模擬一套,成本高,如果後期介面有改變,自己模擬的那套資料又不行了。
後端資料已經開發好,介面也準備好了,本地需要代理線上資料進行測試。這裡有兩個費神的地方,一是需要代理,否則可能跨域,二是介面資訊如果改動,後期接你專案的人需要改你的程式碼,麻煩。
不方便控制輸出。為了讓首屏載入速度快一點,我們期望後端先吐出一點資料,剩下的才去 ajax 渲染,但讓後端吐出多少資料,我們不好控。
當然,存在的問題遠不止上面列舉的這些,這種傳統的方式實在是不酷(Kimi 附身^_^)。還有一種開發流程,SPA(single page application),前後端職責相當清晰,後端給我介面,我全部用 ajax 非同步請求,這種方式,在現代瀏覽器中可以使用 PJAX 稍微提高體驗,Facebook 早在三四年前對這種 SPA 的模式提出了一套解決方案,quickling+bigpipe,解決了 SEO 以及資料吐出過慢的問題。他的缺點也是十分明顯的:
頁面太重,前端渲染工作量也大
首屏還是慢
前後端模板複用不了
SEO 依然很狗血(quickling 架構成本高)
history 管理麻煩
問題多的已經是無力吐槽了,當然他依然有自己的優勢,我們們也不能一票否決。
針對上面看到的問題,現在也有一些團隊在嘗試前後端之間加一箇中間層(比如淘寶UED的 MidWay )。這個中間層由前端來控制。
JavaScript
+----------------+
| F2E |
+---↑--------↑---+
| |
+---↓--------↓---+
| Middle |
+---↑--------↑---+
| |
+---↓--------↓---+
| R2E |
+----------------+
+----------------+
| F2E |
+---↑--------↑---+
| |
+---↓--------↓---+
| Middle |
+---↑--------↑---+
| |
+---↓--------↓---+
| R2E |
+----------------+
中間層的作用就是為了更好的控制資料的輸出,如果用MVC模型去分析這個介面,R2E(後端)只負責 M(資料) 這部分,Middle(中間層)處理資料的呈現(包括 V 和 C)。淘寶UED有很多類似的文章,這裡不贅述。
二、核心問題
上面提出了在業務中看到的常見的三種模式,問題的核心就是資料交給誰去處理。資料交給後臺處理,這是模式一,資料交給前端處理,這是模式二,資料交給前端分層處理,這是模式三。三種模式沒有優劣之分,其使用還是得看具體場景。
既然都是資料的問題,資料從哪裡來?這個問題又回到了介面。
介面文件由誰來撰寫和維護?
介面資訊的改動如何向前後端傳遞?
如何根據介面規範拿到前後端可用的測試資料?
使用哪種介面?JSON,JSONP?
JSONP 的安全性問題如何處理?
這一系列的問題一直困擾著奮戰在前線的前端工程師和後端開發者。淘寶團隊做了兩套介面文件的維護工具,IMS以及DIP,不知道有沒有對外開放,兩個東西都是基於 JSON Schema 的一個嘗試,各有優劣。JSON Schema 是對 JSON 的一個規範,類似我們在資料庫中建立表一樣,對每個欄位做一些限制,這裡也是一樣的原理,可以對欄位進行描述,設定型別,限制欄位屬性等。
介面文件這個事情,使用 JSON Schema 可以自動化生產,所以只需編寫 JSON Schema 而不存在維護問題,在寫好的 Schema 中多加些限制性的引數,我們就可以直接根據 Schema 生成 mock(測試) 資料。
mock 資料的外部呼叫,這倒是很好處理:
JavaScript
typeof callback === "function" && callback({
json: "jsonContent"
})
typeof callback === "function" && callback({
json: "jsonContent"
})
在請求的引數中加入 callback 引數,如 /mock/hashString?cb=callback,一般的 io(ajax) 庫都對非同步資料獲取做了封裝,我們在測試的時候使用 jsonp,回頭上線,將 dataType 改成 json 就行了。
JavaScript
IO({
url: "http://barretlee.com",
dataType: "jsonp", //json
success: function(){}
})
IO({
url: "http://barretlee.com",
dataType: "jsonp", //json
success: function(){}
})
這裡略微麻煩的是 POST 方法,jsonp 只能使用 get 方式插入 script 節點去請求資料,但是 POST,只能呵呵了。
這裡的處理也有多重方式可以參考:
修改 Hosts,讓 mock 的域名指向開發域名
mock 設定 header 響應頭,Access-Allow-Origin-Control
對於如何拿到跨域的介面資訊,我也給出幾個參考方案:
fiddler 替換包,好像是支援正則的,感興趣的可以研究下(求分享研究結果,因為我沒找到正則的設定位置)
使用 HTTPX 或者其他代理工具,原理和 fiddler 類似,不過視覺化效果(體驗)要好很多,畢竟人家是專門做代理用的。
自己寫一段指令碼代理,也就是本地開一個代理伺服器,這裡需要考慮埠的佔用問題。其實我不推薦監聽埠,一個比較不錯的方案是本地請求全部指向一個指令碼檔案,然後指令碼轉發URL,如:
JavaScript
原始請求:http://barretlee.com/api/test…
在ajax請求的時候:
$.ajax({
url: "http://<local>/api.php?path=/api/text.json"
});
原始請求:http://barretlee.com/api/test.json
在ajax請求的時候:
$.ajax({
url: "http://<local>/api.php?path=/api/text.json"
});
php中處理就比較簡單啦:
JavaScript
if(!isset($_GET["page"])){
echo 0;
exit();
}
echo file_get_contents($_GET["path"]);
if(!isset($_GET["page"])){
echo 0;
exit();
}
echo file_get_contents($_GET["path"]);
Ctrl+S,儲存把線上的介面資料到本地的api資料夾吧-_-||
三、小結
本文只是對前後端協作存在的問題和現有的幾種常見模式做了簡要的列舉,JSON Schema 具體如何去運用,還有介面的維護問題、介面資訊的獲取問題沒有具體闡述,這個後續有時間會整理下我對他的理解。