基於 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 提交的消息的特殊標記來決定構建哪些模塊,例如構建 「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%。
成果
至此,我們用一個非常簡單的技術方案實現了設計目標。由於任務調度器的職責非常簡單,不對業務有侵入,因此我們很快速的在幾個大項目中完成部署,和業務中原有的構建腳本配合完成增量構建與發布的任務。
上圖是我們一個大型項目,倉庫中有 600 個左右的 js 模塊。採用增量構建後,持續集成系統從一個版本從代碼提交、構建、發布通常一到兩分鐘即可完成。如果關閉增量構建,這個過程將是十分鐘以上。
這個任務調度程序它在我們內部叫做 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評為「應用架構、基礎設施和集成類最酷供應商」