先後端分離:分離開發,一體發佈

先後端分離開發實踐了好久了,前兩天須要把一個項目上線,準備 SSL 證書時發現,竟然須要申請 3 個證書(1 年期免費的證書只能對單個子域名申請),這 3 個域名是:html

  • sys.project.cn,Web 應用前端
  • api.project.cn,應用後端 RESTful API
  • m.project.cn,移動端

屁大點個項目,須要搞得這麼複雜?用子路徑不行嗎?就像這樣:前端

  • //sys.project.cn/
  • //sys.project.cn/api/
  • //sys.project.cn/m

回答我說,不行!由於是先後端分離方式開發的,每一項都是單獨的項目,單獨發佈出來,只能分別做爲網站發佈……我那感受,就像喝了兩瓶二鍋頭,不只醉了,並且上頭,就差發酒瘋了!node

且不說是否是必定要分離發佈的問題,就算各自獨立發佈,至少有三種方案能夠發佈成子路徑:web

  • 虛擬目錄或純靜態的子目錄
  • IIS 站點上「添加應用程序」
  • 使用 Nginx 反向代理

但這不是重點,重點是:數據庫

分離開發就必定得分離發佈嗎

自從應用先後端分離開發模式以來,分工明確,合做愉快。最近後端通常是用 NET Core 開發,前端使用的 Vue 技術棧。若是偶爾後端人力不足,有點數據庫基礎的前端工程師還能夠拿 Node.js 幫着實現一部分後端需求。移動端的 Android 團隊已經精簡得只剩下一我的了,只須要維護一個框架應用,處理點硬件調用,把移動端頁面往裏一套就能解決問題。npm

各團隊已經習慣了分離開發,除了討論接口設計,其餘時候團隊間交流最多的可能就是:「API 測試地址是啥,我須要聯調一下。」因此各團隊也習慣了本身發佈,公佈地址給其餘團隊測試、聯調。長此以往,竟然造成了分離開發就得分離發佈的印象。後端

對於較大型一些的項目來講,分離發佈多是必要的:純靜態的前端部分能夠發佈到 CDN,後端部分能夠發佈到多個服務器上外加一層負載均衡。可是對於使用人數不過幾百人,併發最多幾十人的小型應用來講,就一臺應用服務器,把全部東西揉吧揉吧,放一塊兒就能看成一體式開發的 Web 應用發佈出來,真不必去分離。前端工程化

就上面的例子來講,除了應用後端須要跑程序,須要 NET Core Runtime,另外兩項全是純靜態。然而,api

A: 另外兩項不是靜態的,由於要經過構建生成!
B: 什麼構建?
A: Vue 框架寫的,須要經過 npm run build 構建了才能發佈。
B: 那麼,構建結果是否是純靜態的?
A: 構建結果應該不是純靜態的吧,須要在 IIS 上建站點發布。
B: 那麼,構建結果直接用瀏覽器能夠打開嗎?不用 IIS,只用靜態 http-server 能夠部署嗎?
A: 好像能夠
B: 那就是純靜態!跨域

這是一個插曲,不過這得強調一下,「構建」這一過程的結果,不必定就非得是動態的 Web 應用。咱們已經在前端工程化上實踐了這麼久,應該瞭解:前端工程化以後,構建的結果是靜態的,不須要在服務器上跑程序,只須要服務器按 URL 提供靜態資源。

分析下後端應用的發佈內容

如今來看一下後端發佈的結果(部分)

.../api_publish
  |-- wwwroot/
  `-- *.dll

程序中,全部 API 都是經過路由中間件解析 URL 以後轉發到各 Controller 的。假如發佈後綁定了域名 api.project.cn,那麼:

  • //api.project.cn/ 打開的是項目模板提供的一個默認頁面,這個頁面在 wwwroot 中 —— 對了,wwwroot 就是這個 Web 應用的靜態資源目錄
  • //api.project.cn/api/... 這個子路徑下提供全套 Web API 服務

由於應用後端目前只提供 Web API 服務,wwwroot 裏只不過放了一些沒用的靜態資源 —— 都是建立項目時模板提供的靜態資源,徹底能夠刪得一個不剩。wwwroot 中的內容刪乾淨以後,訪問 http://api.project.cn/ 會獲得一個 404,但不要緊,由於 API 無缺!

那麼,若是把 wwwroot 裏放上前端構建的結果呢?

看看前端項目結構

.../project_root
  |-- src/    <-- 源文件
  |-- dist/   <-- 構建結構(發佈目錄)
  |   |-- index.html       <-- 入口頁面
  |   |-- assets/          <-- 資源(圖片等)
  |   `-- *.js;*.js.map    <-- 構建出來的 js 腳本等
  |-- node_modules/        <-- npm 包緩存
  `-- *       <-- 項目配置、說明等

這個結構中,dist 目錄是 npm run build 構建出來的,這是一個發佈目錄,只有 dist 中的內容須要部署到 Web 服務器上。

揉一會兒

如今把 dist 目錄放在後端發佈目錄 api_publish 中去,更名爲 wwwroot,替換掉原來的 wwwroot,Api 的發佈目錄就變成了這樣:

.../publish
  |-- wwwroot/    <-- 前端構建結果:dist
  |   |-- index.html
  |   |-- assets/
  |   `-- *.js;*.js.map
  `-- *.dll

這個目錄在 IIS 裏部署出來,直接訪問 //api.project.cn/(以前綁定的域名),咱們會毫無懸念地看到前端頁面出來了。因爲前端頁面中 Ajax 調用的 Base URL 都是 //api.project.cn/,因此 API 調用也沒有問題。

不過是 Web 應用的主頁通常不會經過 //api.project.cn/ 來訪問,因此綁定 sys.project.cn 域名來訪問。//sys.project.cn/ 沒有問題,能夠打開頁面。以前綁定的 api.project.cn 並未取消,因此 Ajax 調用也沒有問題。

注:從 //sys.project.cn/ 經過 Ajax 調用 //api.project.cn/ 可能會存在跨域問題,不過在這個案例中,跨域問題早就處理過了,不細說。

申請 SSL 證書

接下來,開始申請 SSL 證書。若是隻申請一個證書(收費證書很貴的),是該申請 api.project.cn 的,仍是 sys.project.cn 的?

無論 api.project.cn 仍是 sys.project.cn 均可能在接收到的請求中包含敏感信息,也可能在響應中包含敏感數據。別的不說,Ajax 調用就已經涉及到了兩個部分的信息交換,任何一方不安全,總體都是不安全的。

可是隻有一個證書,就得放棄一個域名,放棄哪個比較好?

sys.project.cn 是應用入口,應該告知用戶,而 api.project.cn 是在頁面中隱含調用的,因此應該放棄 api.project.cn。而放棄 api.project.cn,就意味着須要把 Web API 部署爲 sys.project.cn 的子路徑中,即 //sys.project.cn/api/。而後把前端 Ajax 調用的 Base URL 改成 //sys.project.cn/api/ 便可。

這不,//sys.project.cn///sys.project.cn/api 就把先後端揉合在一塊兒了,搞成一體式發佈。

再來個移動端

對了,還有一個針對移動端的前端靜態資源須要發佈,它和發佈應用前端原理同樣,可是得發佈到 .../wwwroot/m/。問題是,須要以虛擬目錄的形式發佈嗎?

其實這個問題不是難題,純靜態的東西,怎麼揉都行。

一體式發佈

若是,三端不是同時發佈,而是各有各的生命週期,那最好發佈成三個目錄:

  • .../publish/api/,部署爲 IIS 站點(刪除掉其中的 wwwroot 目錄)
  • .../publish/sys/,作成符號連接(Windows 下用 Junction)到 .../publish/api/wwwroot
  • .../publish/mobile/,能夠直接在 IIS 中部署成 /m 虛擬目錄,也能夠 sys 那樣作成一個符號連接

對於多數小項目來講,三端都是同時發佈、聯合測試的。這種狀況下,就可使用一個構建腳本將前端 dist 、移動端 dist 和 Web API 發佈目錄拷貝到一塊兒,按以下結構發佈:

.../publish/
  |-- *.dll
  `-- wwwroot/          <-- 前端構建結果:dist
      |-- index.html
      |-- assets/
      |-- *.js;*.js.map
      `-- m/            <-- 移動端構建結果:dist
          |-- index.html
          |-- assets/
          `-- *.js;*.js.map

分離式開發

一體式發佈說完了,再回過頭來講說分離式開發。

由於一開始的問題出如今部署的時候,因此咱們反推了一體式發佈的過程。但實際上,應該反過來,按正常的順序,從項目開始開發的時候來規劃。

項目開始開發,說明它的需求已經肯定下來。那麼,就基本上能肯定用戶該怎麼來使用它,它應該怎樣部署。因此建立項目工做區的時候會想到這樣一個目錄結構:

.../project
  |-- wwwroot/    <-- 前端靜態資源
  |    `-- m/     <-- 移動端靜態資源
  |-- **/*.cs     <-- 源代碼
  `-- *           <-- 項目及其餘各類配置文件等

而後進行分工計劃:

  • 前端一組寫 wwwroot,但要把 wwwroot/m 這個目錄保留給二組
  • 前端二組寫 wwwroot/m
  • 後端組寫 project

若是直接在整個工做區中協做複雜度會比較高,並且前端工程師看到後端代碼會頭痛,後端工程師看到前端代碼也頭痛。因此拆分項目,同時決定構建方法:

  • wwwroot 建立一個前端項目 web,構建輸出到 wwwroot
  • wwwroot/m 建立另外一個前端項目 mobile,構建輸出到 wwwroot/m
  • project 從源文件中刪除 wwwroot,不關心前端過程
  • 構建方法:按以下順序總體構建
    • 構建 project,並總體發佈到 .../publish/
    • 構建 web,獲得 .../web/dist,將其拷貝到 .../project/wwwroot/
    • 構建 mobile,獲得 .../mobile/dist,拷貝到 .../project/wwwroot/m/

而後各組領任務,項目技術負責人開始建立項目文件,編寫開發規範……


喜歡此文,點個贊 ⇙

支持做者,賞個咖啡豆 ⇓

相關文章
相關標籤/搜索