先後端分離開發實踐了好久了,前兩天須要把一個項目上線,準備 SSL 證書時發現,竟然須要申請 3 個證書(1 年期免費的證書只能對單個子域名申請),這 3 個域名是:html
屁大點個項目,須要搞得這麼複雜?用子路徑不行嗎?就像這樣:前端
回答我說,不行!由於是先後端分離方式開發的,每一項都是單獨的項目,單獨發佈出來,只能分別做爲網站發佈……我那感受,就像喝了兩瓶二鍋頭,不只醉了,並且上頭,就差發酒瘋了!node
且不說是否是必定要分離發佈的問題,就算各自獨立發佈,至少有三種方案能夠發佈成子路徑:web
但這不是重點,重點是:數據庫
自從應用先後端分離開發模式以來,分工明確,合做愉快。最近後端通常是用 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 證書。若是隻申請一個證書(收費證書很貴的),是該申請 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/
而後各組領任務,項目技術負責人開始建立項目文件,編寫開發規範……
喜歡此文,點個贊 ⇙
支持做者,賞個咖啡豆 ⇓