以SVN+RMS爲核心的發佈系統,對前端開發的影響上來看,存在如下問題:
- 覆蓋式的發佈,容易致使線上問題。 js一旦發佈,就有可能被任意其餘頁面使用。被引用的越多,就越重要。一旦核心js出現故障,影響面巨大。
- 發佈的基本粒度過於細節,基本發佈單位是文件。相對後端每次發佈整個應用,文件粒度的發佈體現出對應用複雜度缺少深刻理解。
- 手工挑選文件發佈,容易發生人爲錯誤。SVN+RMS的模式使得前端開發在各類GUI工具間切換,使得發佈環節效率低下。在前端工具逐漸命令行,一鍵式,自動化,集成編輯器的大趨勢下,愈發顯得效率低下和對前端開發者不友好。
- 在發佈與版本管理系統深度耦合的狀況下,使用中心式版本系統的SVN無力高效的支持分支開發、主線發佈的開發/上線模式。在版本控制領域,SVN合併分支效率低、有瑕疵的分支合併算法、基於文件而非倉庫的版本管理,容易引入Bug,已是一個過期工具。
以上問題在項目交接的場景中會更加容易犯錯,如下是一個案例:
開發者甲實現特性1修改了A文件而且提交到SVN。於此同時,開發者乙爲了實現特性2同時修改了A、B兩個文件,也提交到了SVN。因爲工做安排變化,甲交接特性1給開發者丙,開發者丙從SVN更新整個應用代碼,在本地繼續特性1的bug修改(在不知道特性2其實也被加入進來的狀況下)。上線時,開發者丙在RMS中,觀察到文件B可能也須要被髮布的狀況下,因爲被告知特性1僅與文件A有關,爲了最小影響,選擇只發布文件A上線。因爲文件A依賴文件B,上線後出現故障。
固然,若是使用了svn分支,這個問題也能避免。問題是,svn分支很厚重。前端
改進目標:
- 讓前端Assets發佈過程更加安全、高效、工程化。在解決全部現狀問題的基礎上,發佈體系還應可以達成如下目標:
- 一旦發佈出現問題,前端可以快速回滾
- 流暢的支持beta,灰度發佈( 比目前更容易的)
- 簡化發佈步驟,減小犯錯的環節
核心機制
一、非覆蓋發佈
發佈的Assets永遠不會覆蓋線上代碼。基於這個機制,給每次發佈的文件/模塊/應用一個版本號/時間戳,保證文件名不與線上重名。一方面,前端代碼有由於其容易被引用的特色,實際上已成爲一種「一旦發佈即永遠存在」的服務。另外一方面,這樣作還可以帶來如下好處:git
- 不覆蓋線上文件,不會影響未知的引用模塊/頁面。
- 再也不須要預發環境驗證,簡化產品發佈流程,減小工做量的同時減小犯錯。
- 不用擔憂誤發佈。由於前端老是先發布。這樣發佈後還有一次機會作「真正的線上測試」。
- 發佈工程而非文件。發佈粒度從文件轉換到項目。前端針對產品總體發佈,每次發佈都是一個項目的某個總體狀態。直接效果是規避掉全部漏發js文件。其深遠意義更在於,爲前端提供一個工程化思考的底層環境。
二、自動化
解決此方案給前端開發效率帶來的問題算法
- 靜態資源引用[^1]的路徑變動。靜態資源引用的/文件名將會攜帶版本/時間戳信息,一旦產生一次發佈,大量的引用路徑變化會引入不少手工勞動。
- 動態資源引用[^2]的路徑變動。模塊加載路徑也會攜帶版本/時間戳信息。在發佈時修改大量動態資源引用路徑的會引入不少手工勞動,增長引入錯誤的機率。
這樣前端須要一套調試、構建工具,靈活高效的處理在聯調、測試、預發、發佈、緊急Bugfix等各類場景下,對站點、項目、模塊、組件的發佈問題。windows
三、從SVN轉移到GIT
這是一個有助於全面提高效率的轉變。後端
- 首先這種轉變對於解決問題1所提到的誤發佈有幫助;
- 其次對於問題2的分支/主幹式的發佈方式有自然的良好適應性;
- 最後,GIT的運行包提供了一個很是強大的命令行環境,
對於問題3所提到的效率困境也有很大幫助。安全
SVN的版本粒度是文件級,GIT的版本粒度是倉庫級。GIT認爲,版本管理的最小單位應該在倉庫,項目在某個時刻的全部文件構成的「快照」體現了一個真正「版本」,所以,每一個「版本」都應該保證本身是可工做的最小特性集合。這是GIT與SVN在版本管理哲學上的本質區別。這個重要的特性使得前面提到的項目交接的案例可以得以解決。服務器
GIT中,分支操做成本極低,僅僅體現爲一個本地文件指針更改。高效強大的分支特性使得合併分支,和基於分支的開發成爲一件愉悅的事情。在SVN中每當啓動一個分支時都當心翼翼相比,GIT能夠隨時隨意的開啓、合併分支。架構
在windows平臺下GIT提供了全套命令行環境有助於提高前端的工具化程度,提升前端開發者爲本身製造工具的可能性。前端構建
解決方案
- 代碼直接經過GitLab發佈。經過GitLab發佈的內容,在SVN將不可見。
- 將不影響在SVN維護的老代碼,新項目啓動逐步經過 GitLab作版本管理,慢慢廢棄SVN。
- GitLab上,按照各前端團隊的需求爲各團隊創建本身的Group。一個團隊能夠有多個 Group[^4]。Group是受控的,由SCM團隊統一管理。須要發佈的Git倉庫放在團隊Group下。
- 每一個須要發佈的Git倉庫須要在GitLab配置中中指定一個該倉庫的發佈路徑,鼓勵將demo和Assets放到同一個庫中維護。發佈時只發布構建目錄。 開發時候對開發人員友好,上線後對線上環境友好。基於此思想,前端代碼必然會存在兩種型式,將來前端構建會愈來愈流行。
- 在SCM的視角,從新理解「應用垂直化」的含義。前端代碼有本身的倉庫,構建後的ASSETS和模板成爲對應用的輸出,在應用的倉庫中有一個路徑存放或者前端代碼乾脆拆分出來。
發佈路徑
非覆蓋發佈
Git倉庫的內容發佈路徑按照http://a.tbcdn.cn/g/[Group]/[Git倉庫]/[Tag]/[發佈路徑]的規則發佈。其中「發佈路徑」是一個Gitlab新增配置項。編輯器
覆蓋發佈
提供簡單發佈接口,不增長時間戳(Git Tag)路徑,直接將組件發佈到對應路徑。這樣作的緣由是組件級開發,其發佈路徑也是對外接口的一部分,須要組件開發者徹底掌握其最終發佈路徑。
發佈路徑爲:http://a.tbcdn.cn/g/[Group]/[Git倉庫]/[發佈路徑]
發佈路徑跟Git強行約定而非配置的緣由以下:
在團隊內基於約定大於配置的思路,可以提升效率。
經過GitLab的自然檢查重複倉庫的機制,保證倉庫發佈不會覆蓋線上路徑。
工做流
- Git倉庫中master分支沒有權限直接push。全部的開發都在daily分支上進行。daily分支的命名爲daily/x.y.z,其中x.y.z是以數字或者點符號組成的字符串,用來標記版本,如1.2.1 、20130401。
- 每當開始一個項目,本地啓動一個**daily/x.y.z**分支,在本地分支上進行開發。
- 本地分支開發完成,須要發佈到平常環境測試或者聯調時,推送 dayly/x.y.z分支到gitlab。gitlab將經過hook將代碼實時發佈至平常環境。
- 聯調完成,經過測試,須要最終發佈上線時,給 daily/x.y.z分支打標籤(又叫作tag或者里程碑) publish/x.y.z。推送該標籤到gitlab服務器,作一系列檢查後,最後部署文件到CDN。一旦一個daily分支被髮布。服務端將刪除遠程daily分支,而且拒絕再次被推送此版本號。這樣作的目的是保證版本號不會重複發佈。
- 修改線上Bug時,須要從新拉出daily分支,而且以新的版本號發佈。
影響分析
新發布方案與現有方案最大的不一樣有兩點。
- 時間戳由發佈系統強制增長。時間戳致使的Assets路徑變動引入更多的工做量。各團隊須要一個本身的構建系統或者其餘方案妥善解決這個問題。
- 須要轉變項目組織思路。目前的發佈是單個文件粒度,能夠選擇發佈單個文件。轉變到新方案後,發佈的最小粒度是項目,一次發佈即發佈整個倉庫(和Git的版本管理思路一脈相承的)。採用新方案後,應該更加細粒度,扁平化的組織倉庫結構,將真正高內聚的一些頁面和組件組織到一個項目中,對項目架構有必定要求。
- 新方案基於整個倉庫的發佈、以及上線後還有一次機會作真正的線上測試,這些機制可以比較好的解決本文最初提到的極端案例。