探究 :深入聊聊前後分離架構
前後分離,一直是一個相當泛泛的問題,前後分離到底好不好?沒有絕對的對,沒有絕對的錯,業界就這個問題已經激烈的探討幾年了.出現討論的點在於:分離當然是好的,但是以什麼樣的服務需要進行前後拆分?拆分到什麼粒度?前後端如何配合?
截圖時間: 2018-08-30 - Github
我們隨意在 Github 輸入前後分離關鍵字,看下搜尋的結果: 1K 的庫 11k 的 Issues 足以說明前後分離的趨勢,可以想象激烈程度,業界比較有名的討論:Web 前後端分離的意義大嗎?,值得一提的是:前排對於這個問題討論比較深刻的大部分都是全棧工程師。因為全棧對全域性的瞭解相對比單純做前端、後端全域性觀念更強一些,考慮的問題更多一些。
篩簡歷引發的思考和分析
後端職位的怪圈
在公司的簡歷庫隨手截幾個區域性的圖,近兩年面試過很多的 1-3 年 java 開發者,在篩選簡歷和麵試過程中,也發現了幾個問題:相當多一部分 javaer 技術棧上總是多了那麼個 HTML ajax jquery bootstrap easyUi ,看起來很唐突,如果面試提到了前端技術棧,基本沒有能答的很好的,甚至有的人連 原型鏈 都不知道。這也是大部分人對全棧的誤解,其實我是不太感冒這樣的簡歷的,因為沒有什麼亮點,技術棧不是寫的越多越好,總結起來:他們對前端的掌握很基礎,勉強能勝任一些業務上的工作。那為什麼這麼多人都掌握一些前端技術呢?我分析可能有三點:
思考原因:
-
培訓機構的興起,機械化的教學
-
求職者自身的興趣
-
一些公司的技術棧不全,對技術沒有追求,大部分用的幾年前的架構,前後業務耦合很大,市場缺口大
分析
因為我也維護過幾個月的敏感專案,深有體會,只寫服務端的人是無法勝任這項工作的, 如果多數的 開發者 這樣的簡歷,可以推測:現在的 IT 行業中前後端糅雜一起的架構還是存在、並且有一個量級,這導致他們不得不尋找一些懂得一點前端技術的人來開發專案,減少溝通的成本,加快專案的進度,這也就催生了很多所謂的 web 開發培訓機構。
你問我當年維護的開心嗎?一會告訴你。
什麼是前後分離
前後端分離並不是什麼新鮮事,到處都是前後端分離的實踐。然而一些歷史專案在從一體化 Web 設計轉向前後端分離的架構時,不可避免的會遇到各種各樣的問題。由於層出不窮的問題,甚至會有團隊質疑,一體化好好的,為什麼要搞前後端分離?說到底,還是技術和思維方式沒轉變過來。
一體化模式其實在上一開篇:縱觀歷史演變 中已經提到過了,不在贅述。
前後分離看起來應該是這樣的:
前後分離就是在架構層次上 構建專案或對現有的專案 客戶端 服務端 分離開,減少前後端程式碼的耦合度,大家一致認同的前後端分離的例子就是***SPA(Single-page application)*** ,所有用到的展現資料都是後端通過 JSON 但不僅限於 JSON 的方式提供的,前端只管展現,提供更好更絢的互動,後端只管提供更健壯的高可用服務。
千萬不要有先寫專案,寫完再重構的想法,專案初期能一步到位最好,何必再去重構,然後不得已拋棄一些已經寫完的元件、庫浪費人力呢?
前後分離解決了什麼問題
每個人各盡其職
好的開發者是可與不可求的,若尋找一個 優秀的 full_stack 更是難,從校招進行培養也不太實際,招一個能力一般的程式設計師,技術驅動性比較差,甚至拖慢產品迭代。分離開來我們就可以專注於 前端、 服務端 領域去尋找專業的人才。
解耦
前端後端程式碼大量耦合程式碼看起來是這樣的:
看看簡單例子吧:
//(node端處理)
if (is_weixin()) {
init([
'api',
'image',
'xxx',
'...',
], function () {
<%- doSomeGloble %>
});
} else {
}
//接收node端一些資料
let blogs = <%- blogs %>;
let users = <%- users %>;
複製程式碼
這還不是 JAVA 模板 而是相對輕量、優雅的 NODE 的 EJS 渲染的,這還好,我見過更令人難受的程式碼,經常為了一個問題要回頭看 N 多程式碼,這裡就不寫了。
那麼前後分離如何讓它們解耦變得更清晰?後面會結合服務端統一補充。
什麼專案不適合前後分離
blog、文件
你說你搭建一個部落格、 API 文件系統 這種小專案,一個人就可以開發。搞了一個前後分離,需要分離部署。又增加了 SEO 的複雜度,增加了開發的週期、增加了使用者部署的難度,何必呢?當然,如果只是技術實踐的一種學習方式,還是歡迎的。
前後分離帶來的問題,如何解決?
溝通成本問題
前端妹子:哥,獲取全部部落格調哪個介面?
哦,昨天不是發你檔案了嗎
前端妹子:我找不到了?
哦,等下吃晚飯發你啊
前端妹子:哥,產品提出根據手機殼自動換主題的需求,你有介面嗎?
... 我看看...應該...沒有!可能需要 Python 的老哥支援!你去找他要吧
前端妹子:哥,你根據 TAG 獲取部落格的介面寫完了沒?介面是啥?我好渲染資料啊
沒等等......
這顯然是不規範的,我們期望的是前端後端先約定一個介面協議,後端沒完成時,前端自己 mock 測試資料,前端找不到介面的時候,直接檢視 API ,根據這個介面協議我們前後端統一程式設計,那麼我們如何處理呢?
如何降低溝通成本? 後端資料服務化,走統一的 REST 介面規範輸出,降低前後端介面定義的溝通成本。避免“口頭說明”的方式。
什麼是 RESTful API ? 所以RESTful API就是REST風格的API。 那麼在什麼場景下使用RESTful API呢?在當今的網際網路應用的前端展示媒介很豐富。有手機、有平板電腦還有PC以及其他的展示媒介。那麼這些前端接收到的使用者請求統一由一個後臺來處理並返回給不同的前端肯定是最科學和最經濟的方式,RESTful API就是一套協議來規範多種形式的前端和同一個後臺的互動方式。
我通常用 swagger + mock 平臺生成標準的 RESTful API,同時也支援擴充套件多個程式語言例如:Go Python
SEO 問題
以 vue + webpack 的 SPA 為例,沒有了後端模板返回的 HTML,前端渲染並不被搜尋引擎的爬蟲接納。在日後實戰 SEO 之前先通俗渲染唄爬蟲識別的區別:
seo 本質是一個伺服器向另一個伺服器發起請求,解析請求內容。但一般來說搜尋引擎是不回去執行請求到的 js 的。也就是說,如果一個單頁應用,html 在伺服器端還沒有渲染部分資料資料,在瀏覽器才渲染出資料,而搜尋引擎請求到的 html 是沒有渲染資料的。 這樣就很不利於內容被搜尋引擎搜尋到。 所以服務端渲染就是儘量在伺服器傳送到瀏覽器前 頁面上就是有資料的。
以部落格為例簡單聊聊:
- 靜態服務
<div>我是正文1</div>
<div>我是正文2</div>
<div>我是正文3</div>
複製程式碼
爬蟲直接抓到 html 解析 - 生成索引
- 傳統後端渲染
@RequestMapping("/index")
public String index(HttpServletRequest request,HttpServletResponse response){
return "welcome";
}
複製程式碼
這裡就比較有意思了,比如我們開啟的網址是:
http://host:port/index
實際充當 Controller 的是 服務端,服務端直接返回渲染好的網頁給你,爬蟲拿到的也是一樣,所以 SEO 沒啥太大的問題。
- 前後分離 SPA
let blogs = [];
this.axios.get('/index, {})
.then(res => {
blogs = res.data;
})
.catch(err => {
console.error(err);
});
<!--前端模板渲染dom-->
<div v-for="(item, index) in blogs" :key="item">
複製程式碼
同樣我們輸入
http://host:port/index
注意:SPA 通常有自己的路由策略,這也就是前端 MVC MVVM 中的 第一個 M
一個典型的 SPA 站點
我們輸入網址先到了這個頁面,然後再去非同步請求伺服器,再由前端頁面渲染,又是單頁面服務如果我們不做任何處理,那麼你將被各大搜尋引擎拋棄。
如何解決?
只要做 SEO 的產品就要做服務端渲染,如果你對 SEO 需求有,但要求並不高,僅部分頁面、可以曲線救國
nodejs 出現之前有兩種解決方式,一是做一動一靜兩套頁面,伺服器判斷請求來自蜘蛛就呈現靜態頁,否則呈現動態頁;二是伺服器架設虛擬瀏覽器軟體,請求過來了先讓虛擬瀏覽器跑一遍,再將得到的靜態頁面返回給客戶端。這兩種方式在大型專案上都有效能問題。
有了 nodejs 後主流做法是前後端同構方案,即一套程式碼在瀏覽器端和 node 端都可以執行,從而可以先在 node 端請求資料渲染模板,然後將渲染結果返回給瀏覽器最終呈現。感興趣可以看看 Vue 的SSR方案 Angular 的SSR方案
如何更細緻的研究 SEO 以後再說
跨域
由於採用前後端分離部署,自然不在一個埠,不在一個埠必然跨域,不過這對現在的技術手段來說完全不是問題
開發模式 為了更快更好的開發,dev 下一般採用 node 做代理層,解決跨域,幾乎無障礙開發,而且可以輕鬆切換環境。
部署模式 部署一般不依託 node 進行部署,通常我們釋出到 HTTP 伺服器,與服務端進行通訊,通常使用 nginx 進行正向代理。
總結
我認為近幾年,前後分離是一種趨勢,它的諸多問題正在逐步得到解決,逐漸被大家接受。它確實使我們的架構變得更加清晰,如果你還在猶豫,為什麼不大膽跟我走出第一步呢?
***講了兩章概念我都已經忍不住想要馬上帶大家實踐了***???
關於我
-
目前在寫《從零構建前後分離專案》系列,修正和補充以此為準
-
不斷更新的 專案實踐地址
-
彩蛋:提前預覽下一章傳送門 ?