當前位置:
首頁 > 科技 > 基於 Git、Svn的Commit 實現可增量構建的前端持續集成解決方案

基於 Git、Svn的Commit 實現可增量構建的前端持續集成解決方案

前言


當看到這個標題的時候,我是被吸引的因為很多時候在持續集成方面都是運維在處理的,在項目場景上還沒處理過這種的。今日早讀文章由廈門歡樂逛 @ 糖餅分享。


正文從這開始~


近兩年由於技術的發展,Web 前端可以通過編譯工具來實現 HTML、CSS、JS 所做不到的事情,從而覆蓋更多的業務,從技術角度實現更多的價值。社區也在不斷的創造更好的編譯、構建工具,例如目前大紅大紫的 Webpack。正因為這些先進的工具,我們工作效率得到了前所未有的提升。當然,我們也需要面對它們所帶來的一些問題:構建速度越來越慢,導致發布速度越來越慢。尤其是在使用持續集成系統來構建的項目中,這個問題越嚴重。


解決構建慢的問題有很多途徑,比如常見的手段是優化構建工具的配置,網上也有很多這樣的實踐經驗文章,這些優化手段大多都是針對具體的工具、本地開發構建進行的,如果使用持續集成伺服器進行構建,社區缺乏一些簡單可靠增量構建解決方案。針對於此,我給大家分享我們前端團隊(廈門歡樂逛)的實踐成果:基於 Git、Svn 的 Commit 實現可增量構建的前端持續集成解決方案。

背景


大約是 2014 年的時候,我們在 Git 伺服器上通過 Githooks 、Grunt 實現了一個複雜的前端增量構建系統:提交代碼到對應分支後伺服器會自動進行增量構建、增量發布。這套系統這在當時看來自動化程度已經很高了,解決了本地構建、發布所帶來的效率以及安全風險,版本發布非常快速。當時前端團隊的構建與發布流程:


代碼提交到開發分支:自動構建


代碼提交到主幹分支:自動發布


2014 ~ 2017 年之間,我們業務飛速發展,前端項目越來越多,構建這一塊也被更先進的 Gulp 與 Webpack 代替,而之前基於 Grunt 設計的增量構建系統已經無法適應新業務與技術的需求,項目部署、團隊協作的成本越來越非常高。這迫使我們思考如何實現一個不受具體構建程序約束、跨業務、支持增量構建與發布的標準化解決方案。


決定做這個事情之前,我們先將 Githooks 觸發的構建與發布任務由持續集成系統代替,以讓前端開發流程與工具標準化。


持續集成


「持續集成是一種軟體開發實踐。它倡導團隊開發成員必須經常集成他們的工作,甚至每天都可能發生多次集成。而每次的集成都是通過自動化的構建來驗證,包括自動編譯、發布和測試,從而儘快地發現集成錯誤,讓團隊能夠更快地開發內聚的軟體」


以上是持續集成的概念,一個完整的持續集服務由以下幾個系統組成:


一個自動構建過程,包括自動編譯、分發、部署和測試等。對於前端項目,這裡往往是 Gulp、Webpack、Mocha 等工具來實現。

一個代碼存儲庫,即需要版本控制軟體來保障代碼的可維護性。如 Git 或 Svn 等。


一個持續集成伺服器。如 Gitlab CI、Travis、Jenkins 等。


由於我們公司內部代碼託管平台使用 Gitlab 搭建的,因此直接採用了 Gitlab 自帶的 Gitlab CI 作為構建伺服器,這樣能夠與目前工作流無縫整合在一起。

基於 Git、Svn的Commit 實現可增量構建的前端持續集成解決方案



增量構建


本地開發中,規模較大的項目一般會拆成多個模塊,單獨進行編譯來提高構建速度,根據不同的參數來構建指定模塊。


而在持續集成系統中,最初我們通過判斷 Git 提交的消息的特殊標記來決定構建哪些模塊,例如構建 「users」 模塊:


git commit-m"[publish:users] 修複線上 BUG #456"


這種簡單的開發約定可以讓伺服器做到精確構建,不足之處是需要人工介入,存在風險。例如:開發者修改了公共模塊後,如果忘記構建依賴了它的業務模塊,這很有可能引起線上故障。

理想的情況下,項目開發人員無序關注細節,只需要關注工作本身。測試、生產環境的構建與發布的細節應該完全由持續集成服務完成。


watch


為了實現完全自動化,我們使用檢測文件修改的方式來觸發增量構建,不同於本地開發中的 --watch 模式,我們採用 Git 的 Commit ID 來實現。原因:持續集成系統需要明確的知道任務的成功與失敗狀態,而構建與編譯工具自帶的--watch 會導致進程常駐,無法獲取運行結果。


gitCommit.watch( ./users ,(last,pre)=>{


if(last.id!==pre.id){


exec( cd users && webpack --color );


}


});


// [more code..]


gitCommit.watch() 方法會記錄上一次的提交版本,對比新舊提交版本即可決定是否啟動構建,從而實現增量構建。這種基於版本倉庫的變更對比使用 md5 要高效很多,並且能夠讓發布後的文件和版本庫關聯起來。更加重要的是它是成熟的解決方案,這對系統的穩定性至關重要。

標準化


項目中通常都有自己的構建腳本,如果再添加增量構建邏輯這無疑會加劇構建腳本的複雜度、帶來更高的成本。因此我們設計了一種描述增量構建的任務的配置格式,然後實現任務調度器來解析它們、運行任務,以實現對業務原有構建流程的解耦。例如:


{


"tasks":["users","photos"],


"program":"cd $ && webpack --color"


}


tasks 是要觀察的目標列表,它是文件或者目錄;program 是它們發生變更後的處理命令;$ 被設計為一個變數,運行時解析到當前構建目標。


按需全量構建


在業務中,免不了需要全量構建的情況,例如:導航的替換需要重新構建所有業務模塊。


這種情況下需要添加 dependencies 來描述依賴,以讓任務調度程序能夠處理依賴。例如公共模塊 「common」 發生版本變更,就執行全量構建:

{


"tasks":["common","users","photos"],


"program":"cd $ && webpack --color",


"dependencies":["common"]


}


如果 Npm 的模塊發生版本變更也需要進行全量構建,將 package.json 添加到 dependencies 即可:


{


"tasks":["common","users","photos"],


"program":"cd $ && webpack --color",


"dependencies":["common","package.json"]

}


多進程加速


前端代碼壓縮是一個 CPU 密集型操作,非常耗時。而大部分前端構建工具都是單進程設計的,因此它們都無法利用多核心 CPU 資源。如果業務模塊之間沒有依賴關係,啟動多進程可以加速運行它們。


給 tasks 設計一個並行運行任務的描述格式,例如使用二維數組:


{


"tasks":[["common"],["users","photos"]],


"program":"cd $ && webpack --color",


"dependencies":["common","package.json"]


}


遇到可並行的任務,任務調度程序可根據當前機器的 CPU 核心數啟動對應的子進程數,實現多核加速。

我們在 4 核心 CPU 機器進行測試,啟用多進程後全量構建效率將提高 300%。


成果


至此,我們用一個非常簡單的技術方案實現了設計目標。由於任務調度器的職責非常簡單,不對業務有侵入,因此我們很快速的在幾個大項目中完成部署,和業務中原有的構建腳本配合完成增量構建與發布的任務。

基於 Git、Svn的Commit 實現可增量構建的前端持續集成解決方案



上圖是我們一個大型項目,倉庫中有 600 個左右的 js 模塊。採用增量構建後,持續集成系統從一個版本從代碼提交、構建、發布通常一到兩分鐘即可完成。如果關閉增量構建,這個過程將是十分鐘以上。

基於 Git、Svn的Commit 實現可增量構建的前端持續集成解決方案



這個任務調度程序它在我們內部叫做 ci-task-runner,它的誕生是我們踩了 N 多坑的結果。在多個重要項目的生產環境穩定運行半年之後,我們決定將此作為團隊第一個開源項目公布出來。


ci-task-runner 是一個標準 NodeJS 模塊,它只做一件事情:觀察文件或目錄版本變更,啟動對應處理程序。

因為簡單,所以它非常靈活:


與 Grunt、Gulp、Webpack、Rollup 等編譯、構建工具無縫連接


可以使用 Npm Scripts、Gitlab CI、Travis、Jenkins 等工具啟動它


支持 Git 與 Svn 這兩款版本管理工具


Github 主頁:https://github.com/huanleguang/ci-task-runner


最後,具體要怎麼融合進項目可以到gitlab 上看看。


關於本文


作者:廈門歡樂逛 @ 糖餅


原文:https://github.com/huanleguang/ci-task-runner


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

TAG:前端早讀課 |

您可能感興趣

Springboot集成Kaptcha實現前後端分離的驗證碼功能
集成CAD和Unreal,Mindesk支持在VR中實時3D建模
微軟System Center架構和存儲集成分析
Jenkins+RobotFramework持續集成測試-jenkins環境搭建
緩存架構SpringBoot集成Curator實現zookeeper分散式鎖
Red Hat強化容器與最新版OpenShift的集成
Americanas.com的系統集成
用於遠程協作,Autodesk推InsiteVR+BIM 360集成解決方案
jacoco與jenkins集成實現代碼覆蓋率分析
Intellij idea集成的git頁面進行操作
Google正式集成Kubernetes引擎與GPU服務
Informatica發布基於微軟Azure的集成平台即服務
Unity集成包更新,Oculus遊戲可移植HTC Vive
最新Magic Leap SDK集成了Runtime,允許多程序同時運行
Chrome OS 71正式發布:迎來了更好的Android集成
飛利浦 PHILIPS Fidelio M2LLightning介面集成耳放頭戴式耳機 圖集Soomal
微軟希望Cortana能與Alexa和Google助手集成而
飛利浦 PHILIPS Fidelio M2L「Lightning介面集成耳放」頭戴式耳機 圖集「Soomal」
InfiniteBoosting:集成bagging與boosting的混合演算法
Greenbird被Gartner評為「應用架構、基礎設施和集成類最酷供應商」