前后端分離思考

目錄:

一、什么是前后端分離?

大部分人認同開發微信小程序或SPA(WEB單頁應用)是實現“前后端分離”的。所有業務數據都是“后端應用”通過HTTP接口提供給“前端應用”。一個“完整的應用”被物理隔離為兩個獨立的應用,并由擅長的開發者負責,從而實現職責分離

前端開發者:負責 View 和 Controller 層。
后端開發者:只負責 Model 層,業務處理/數據等。

“前后端分離”是強調“職責分離”,上面應用分離的例子是為了方便理解接受,可以不應用分離。通常應用分離能大量減少不小心的越界行為。

前后端分離后的樣子:

framework.jpg

二、為什么要前后端分離?

根據上圖,只有“web網站”和“React Isomorphic”兩種形態應用沒有自然物理隔離前端和后端。我們存在很多沒有前后端分離的web網站應用(這也是痛苦的根源),而React Isomorphic應用是前后端分離流行后的開發模式(代替web網站應用)。

2.1 清晰前后端職責

分離前:前端開發者提供靜態頁面,后端開發者完成 Controller 和 View 層代碼。但前端開發者經常會插一腳修改 Controller 和 View 層代碼。

分離后:面向用戶的 Controller 和 View 層都由前端開發者做;后端開發者只需復雜 Model 層,提供業務數據接口。

前后端分離后基本不需要相互修改對方代碼。

2.2 提高開發效率

分離前:前端和后端溝通/約定頁面模板的每個字段、字段值的格式、適合模板的數據結構。

分離后:前段和后端溝通需要的 Model 接口。

前后端分離能明顯減少溝通成本;約定的內容也少很多,減少大量聯調時間。

2.3 前端能做更多,后端能更專一

前端可以服務端開發,而且可以不再局限WEB開發,同一套API,前端可以實現SPA、微信小程序、支付寶小程序等。

后端能更專一API開發,不用為UI要求的時間格式、模板布局要求的數據結構發愁。

三、基于Node.js做前后端分離

目前存在很多web網站應用,我們正在用PHP實踐前后端分離。前端同事對PHP不熟悉,成本比較高,所以最終會考慮使用Node.js實踐前后端分離。

這里只討論web網站和React Isomorphic應用,因為其他形態的應用已經物理分離了前后端。

React Isomorphic應用比web網站應用更“先進”,而且Node.js生態已有成熟的方案,所以新項目也會更傾向選擇React Isomorphic應用。

www&isomorphic.jpg

3.1 為什么選擇Node.js而不繼續用PHP?

3.1.1 招聘成本

招會Node.js的前端比招會PHP的前端容易。

3.1.2 學習成本

前端學習PHP語言。語法學習成本不高,但熟悉度還是要時間成本的。

3.1.3 開發成本

開發過程頻繁切換語言。經常會在PHP中寫JS語法,這點比較煩。

3.1.4 服務器性能

在自己服務器測試兩種場景。

服務器配置:

  • 騰訊云服務器(Ubuntu 16.04.1 LTS)
  • CPU: 2核
  • 內存:4GB
  • 帶寬:2M

Node.js環境:

  • Node.js版本:v8.12.0(Alinode v3.12.0)
  • 框架:Egg.js
  • worker進程數:2

PHP環境:

  • PHP版本:7.2.10
  • 框架:Lumen
  • php-fpm最大子進程數:5

兩種場景測試代碼:

場景一,直接輸出字符串,不做任何IO和計算。

PHP效率比Node.js高

Node.js:

// egg-4
async function test(ctx) {
  ctx.body = '<h1>goddess.daifee.com</h1><p>Egg程序</p>';
}
egg-4.png

PHP:

// php-4
$router->get('/test', function () use ($router) {
    return '<h1>goddess-php.daifee.com</h1><p>這是PHP服務</p>';
});
php-4.png

場景二,模擬200ms的網絡請求。

Node.js效率比PHP高。相對“場景一”PHP效率下降明顯,Node.js不明顯。

Node.js:

// egg-4—test2
async function test2(ctx) {
  const start = Date.now();
  await new Promise(resolve => {
    setTimeout(() => {
      resolve(true);
    }, 200);
  });
  const offset = Date.now() - start;
  ctx.body = `<h1>goddess.daifee.com</h1><p>Egg程序 ${offset}</p>`;
}
egg-4-test2.png

PHP:

// ./WeTest_[php-4—test2]_20181014172129.pdf
$router->get('/test2', function () use ($router) {
    $start = microtime(true);
    usleep(200000);
    $offset = microtime(true) - $start;
    return "<h1>goddess-php.daifee.com</h1><p>這是PHP服務 {$offset}</p>";
});
php-4-test2.png

3.2 基于Egg.js框架開發(編碼)

下面用Egg.js框架開發一個頁面為例(瀏覽器端開發模式不需要改變)。

開發一個新頁面(用戶主頁頁),只需要下面4個步驟:

  1. 模板:創建模板文件。
<!-- app/views/user.ejs -->
這里是 ejs 模板
  1. 數據接口:幾行代碼封裝數據接口。
// app/service/user.js
const { Service } = require('egg');

module.exports = class UserService extends Service {
  async get(userId) {
    const url = `https://api.gateway.com/xxx/${userId}`;
    // http請求/ajax
    const response = await this.app.curl(url);
    return response;
  }
}
  1. 控制器:過濾/驗證用戶輸入、驗證權限、調用數據接口、渲染模板。
// app/controller/user.js
const BaseController = require('./base-controller');

module.exports = class UserController extends BaseController {
  async profile() {
    const { params, service } = this.ctx;
    // 只有自己才能訪問自己主頁。不是自己就拋出 403 異常
    this.assertUser(params.userId);
    user = await service.user.get(params.userId);

    await this.render('user', {user: user});
  }
}
  1. 路由:一行代碼聲明路由。
// app/router.js
module.exports = app => {
  const { router, controller, middleware } = app;
  const { authorize } = middleware;
  const { user } = controller;

  // 已登錄用戶才能訪問
  router.get('/users/:userId', authorize.user, user.profile);
}

只負責 Controller 和 View 層的Node.js服務端開發非常簡單。一個企業應用除了開發,還有其他環節需要做好。

3.3 我們還缺什么?

前端開發者可以在服務端寫 Controller 和 View 層代碼,但整個生產環節還缺什么?

3.3.1 前端開發者

既然前端開發者需要做更多,能做更多,所以工作量增加。所以缺前端開發者。

  • 同一個項目,編碼的工作量增加了。
  • 前端同事需要關注、分析、協助維護Node.js服務器。
  • 肯定會有更多的xxx小程序需求。

3.3.2 適合我們的框架和項目腳手架

  • 確定了web網站應用使用Egg框架,還需為不同業務場景的項目創建拿來即用的腳手架。
  • 未確定React Isomorphic應用的框架。我體驗過next.js,是一個不錯的選擇。

3.3.3 構建/部署服務

目前還沒有Node.js項目的構建/部署服務。

基本需求:

  1. 構建:開發者只需關注源碼,“構建服務”自動構建項目。
  2. 發布:支持選擇git tag構建,部署到“生產環境”。
  3. 發布:支持選擇git branch構建,部署到“測試環境”。
  4. 回滾:支持指定版本回滾。
  5. 重啟:支持重啟Node.js服務器。
  6. 發布:允許測試人員發布“測試版本”。

3.3.4 嚴謹的git工作流

需要依據“構建/部署服務”定制嚴謹的git工作流。

3.3.5 風險監控和日志采集

  • 風險監控可以考慮Alinode。
    • 完全免費
    • 支持性能監控、安全提醒、故障排查、性能優化等
    • 支持手動下載性能數據
  • 日志采集接入大數據團隊的服務?

關于React Isomrophic

當時用React全家桶做了一個SPA Demo項目,然后用next.js框架再做一個React Isomorphic版。發現可以復用(copy)98%的代碼,然后花一點時間將 React Router 替換為 next.js 自帶的 Router 即可

基于 next.js 框架 React Isomorphic 應用與 SPA 的開發體驗差不多。

畢竟一套代碼運行于兩個不同環境,React Isomorphic 還是帶來了一些坑:

  1. 需要意識到哪些代碼在2個環境都執行,哪些代碼只在其中一個環境執行。
  2. 立即執行的代碼在2個環境都執行。
  3. React組件生命周期的代碼只在Browser環境執行。
  4. Component.getInitialProps()方法在2個環境都執行。
  5. 小心使用運行環境的“接口”
  6. next.js自帶Router,與“其他Router”肯定存在差異。
  7. 某些組件需要用唯一自增ID或隨機數,這種做法會使服務端于客戶端存在差異。
  8. “服務端”與“客戶端”基本只能用cookie共享“狀態”,要珍惜cookie資源。

參考

  1. http://taobaofed.org/blog/2014/04/05/practice-of-separation-of-front-end-from-back-end/
  2. https://segmentfault.com/a/1190000009329474
  3. https://github.com/lifesinger/blog/issues/184
  4. https://tech.youzan.com/gateway/
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容