作者:張偉(上坡) 淘系技術
轉(zhuǎn)發(fā)鏈接:
https://mp.weixin.qq.com/s/uAppcIC8j44AfDSby3PrTQ
前言
在加入淘寶后,經(jīng)歷了大大小小的開發(fā)和部署方式的更迭,同時也有幸在整個的變革潮流中參與過其中的一些能力的建設。今天從一個親歷者的角度,通過自身經(jīng)歷與向同事考究,從“13年石器時代”、“14年白銀時代”、“15年黃金時代”以及“未來時代”四個階段和大家聊一聊大廠是怎樣開發(fā)和部署前端代碼的。
在阿里的淘系前端團隊,開發(fā)與部署的模式隨著技術的發(fā)展,仍然正在處于不斷變化的過程中。一方面體系內(nèi)外紛繁復雜的能力模塊不斷地向前發(fā)展,另一方面 LSP、DAP 等底層技術基礎也逐漸成熟。在當看我們正在通過集成研發(fā)環(huán)境 IDE 的方式,將上一個階段孵化沉淀的研發(fā)生態(tài)進行再一次的整合升華,將原有的鏈路再次重組,從當下用戶的痛點中找到突破口,發(fā)掘當下各個研發(fā)場景中的最佳能力組合,搭建通用底層平臺,升級變革現(xiàn)有模式。
作為從 14 年實習到 15 年正式進入公司的前端開發(fā),在前身為淘寶前端團隊的 淘系前端團隊 經(jīng)歷了大大小小的開發(fā)和部署方式的更迭,同時也有幸在整個的變革潮流中參與過其中的一些能力的建設。今天從一個親歷者的角度,通過自身經(jīng)歷與向同事考究,以分階段的方式來進行回憶和描述。
回答將整個故事分成四個階段,首先是 13 年左右以代碼發(fā)布存儲、部署改造成 Gitlab 技術體系為主旋律的 "石器時代";14 年左右伴隨著 NodeJS 技術成熟,用前端 JS 語言建設工程化工具的 "白銀時代";從 15 年開始,在借助 NodeJS 技術完成工程化工具嘗試之后,更系統(tǒng)化建設線上線下前端工程化體系的 "黃金時代";以及在當下我們正在通過客戶端、容器、算法等多元化技術打造未來研發(fā)模式的"未來時代"。
石器時代
在 13 年前,前端的研發(fā)模式其實與后端研發(fā)的方式?jīng)]有太大的差異,大部分是基于 SVN 進行 SCM 代碼管理。在完成每天的代碼研發(fā)工作后,通過命令行或者 小烏龜 等工具將代碼上傳到 SVN 服務器中完成一天的開發(fā)流程。在部署階段,通過手動拷貝或者 FTP 上傳的方式,將測試代碼進行上傳到測試服務器上,在完成測試之后,人工檢查下代碼版本及內(nèi)容,然后進一步上傳到生產(chǎn)環(huán)境,完整整個研發(fā)部署流程。
在那個時期,代碼管理工具除了 SVN 之外,也出現(xiàn)了基于 GIT 協(xié)議實現(xiàn)的代碼管理工具 Gitlab。面對 SHA-1 算法帶來的版本檢測便利性、本地分布式的代碼版本控制的靈活性等優(yōu)勢,我們逐步將部門內(nèi)的 SVN 研發(fā)工作流程遷移到了 Gitlab 上。同時這個變化也算是淘系前端研發(fā)變革的起源。
在經(jīng)歷代碼版本管理工具切換帶來的便利同時,我們思考當時較為操作繁瑣、需要人工保證的部署流程是否也能進一步的在新的體系上得到改善。在新版發(fā)布系統(tǒng)的背景下,我們在新的 Gitlab 系統(tǒng)所提供的各種能力中,發(fā)現(xiàn)可以將 webhook 機制進行一定的上層封裝,借助規(guī)則化的操作,來觸發(fā)與發(fā)布系統(tǒng)的關聯(lián),自動完成發(fā)布上線流程。我們基于 publish/版本信息 這樣固定規(guī)則的 Git Tag 來觸發(fā) webhook 事件通知,觸發(fā)發(fā)布系統(tǒng)的調(diào)用上線流程,從而完成了第一個實際意義的前端研發(fā)全自動化發(fā)布流程。
這個階段就像 "石器時代" 般原始,不過在完成了研發(fā)基礎設施這塊如釜底抽薪般的改造之后,為后續(xù)的發(fā)展提供了堅實基礎。同時隨著前端技術發(fā)展的契機,我們也基于這套底層體系進入了新的階段。
白銀時代
在 14 年左右的時候,已經(jīng)誕生 5 年多的 NodeJS 技術也逐漸變得成熟起來,當時團隊基于 NodeJS,產(chǎn)出了一套名為 DEF 的研發(fā)本地端 CLI 終端工具,工具的核心是一套 Node 模塊的安裝、調(diào)用管理機制。工具開發(fā)者通過將研發(fā)功能模塊封裝成 DEF 體系下的 插件 形式,通過不同 插件 模塊的調(diào)用組合,來實現(xiàn)對前端項目的編譯、調(diào)試、上線等操作。
在當時 KISSY 框架研發(fā)體系下,我們借助 NodeJS 的能力,通過正則匹配、 UglifyJS 解析 AST 等方式進行腳本編譯處理,通過 JS 技術開始構建起前端領域的工程化工具,逐漸替代掉了以 JAVA 體系中借助 Ant 平臺實現(xiàn)的工具。
在當時我們除了借助使用 yeoman 等工具來完成初始化流程,也隨著業(yè)務編譯構建邏輯的不斷抽象產(chǎn)出 構建器 這樣的基礎概念。
當時在傳統(tǒng)的項目組織中,構建編譯的配置邏輯與項目的代碼文件是放置到同一個代碼目錄中。從團隊視角看,這塊構建編譯邏輯零散自由,談不上有統(tǒng)一的更新管理邏輯。如果團隊內(nèi)某一類的研發(fā)場景構建編譯工具本身有任何的更新變化,在團隊范圍內(nèi)工具的更新覆蓋將需要消耗非常大的成本;與此同時,在用戶的角度,在相同類型的不同項目中,也存在著大量重復安裝的構建依賴,每一個項目在構建前也都需要安裝一遍構建依賴,在空間和時間上都有一定占比的浪費。
通過 構建器 概念將編譯構建依賴進行收斂、抽象,將項目的編譯依賴維護在一個 npm 包中。這樣編譯邏輯就從多對多變成了一對多,在大幅降低構建邏輯的空間占用的同時,也能較好的復用已經(jīng)安裝的構建依賴,簡化構建環(huán)節(jié),提升構建效率。進一步也為后續(xù)的線上構建體系埋下了伏筆。
在這個階段,NodeJS 技術也逐漸變成了我們除日常頁面開發(fā)之外的又一個基本技能。伴隨著 NodeJS 工具的誕生與規(guī)模應用,前端開發(fā)與部署從 "石器時代" 進入到 "白銀時代"。隨著大家對 NodeJS 體系的基本運用變得愈發(fā)成熟,我們在基礎體系的使用之上,進一步開始進行更深入的思考發(fā)散和抽象設計,開始建設更成熟的前端工程體系。
黃金時代
該團隊完成基于 NodeJS 技術的工程工具以及 Web 服務框架等基礎設施建設之后,在隨后的幾年時間內(nèi),越來越多的更為成熟的線上線下的工程化體系發(fā)展起來。在那個階段設計、建設的服務、工具后續(xù)也逐步形成了如今淘系前端研發(fā)、部署流程中的基礎設施。
? 研發(fā)套件
隨著本地 DEF 工具的發(fā)展,越來越多工具插件雨后春筍般地涌現(xiàn)出來。一方面用戶有著非常多的工具選擇,基本上本地研發(fā)過程中的功能都能在插件生態(tài)中找到;但是另一方面,在實際用戶視角下,在某一個項目開發(fā)的時候,用戶需要對這個項目使用到的插件以及插件用法要有一定的熟悉程度、知道最佳的組合使用方法。隨著項目逐漸變多,對于工具組合的記憶成本變得高起來,同時也需要注意到不同項目之間插件組合的切換。
在百花齊放之后,面對延伸出來的問題,在原有的本地 DEF 工具之上,我們提出了 研發(fā)套件 的概念。通過對本地研發(fā)過程中進行總結(jié)收斂,抽象出 init 初始化、dev 編譯預覽、build 構建、test 測試、publish 發(fā)布 這五個本地工具的功能節(jié)點。將原有的插件能力根據(jù)項目研發(fā)類型進行分類后,總結(jié)沉淀出每一類研發(fā)類型的標準本地工具 --研發(fā)套件。
借助套件概念的封裝,用戶在不同項目之間研發(fā)的時候直接通過 統(tǒng)一的命令 ,就能完成項目研發(fā)對應工具服務的啟動使用。同時在新的本地套件體系,也能針對每一位用戶有著更細利度、靈活的版本指定方式。配備更完善的日志監(jiān)控體系,在使用工具的用戶遇到問題時能實時感知、解決,最大程度保證一線同學本地研發(fā)工具的使用體驗。
? 研發(fā)部署平臺
在借助 Gitlab 的 webhook 能力發(fā)布前端資源的流程成熟之后,一方面在發(fā)布流程上研發(fā)用戶期望有更優(yōu)化的發(fā)布體驗,另一方面團隊對于前端研發(fā)流程更體系化、結(jié)構化的流程治理、數(shù)據(jù)統(tǒng)計也有了更高的要求。
在這樣的背景下,我們通過打通原有鏈路上發(fā)布能力,將發(fā)布鏈路中各個環(huán)節(jié)進行更友好的串聯(lián),產(chǎn)出了前端體系下的研發(fā)部署平臺。在體驗上,用戶可以借助一個簡單的命令行命令直接開始發(fā)布任務的啟動,簡化了發(fā)布時 git 發(fā)布 tag 的操作流程。在整個發(fā)布流程中,通過長連接的方式將各個環(huán)節(jié)的運行信息、日志進行返回展示,提供了全新操作的一條發(fā)布鏈路。用戶第一次開始對發(fā)布流程有著更全面的掌控,從開始進行代碼的提交檢測到最后資源 cdn 上線都有著完善的信息披露,極大的提高了發(fā)布體驗。
基于內(nèi)部 NodeJS 實現(xiàn)的研發(fā)部署平臺,在完成了基礎鏈路的打通之后,在更體系化的角度上也逐步地開始作為工程研發(fā)上線流程的基礎,對原有的上線發(fā)布鏈路的進行重塑。將原有流程中的環(huán)節(jié)進行抽象,逐步分散到 構建、檢測、發(fā)布 三個主要步驟。在隨著業(yè)務研發(fā)類型從 PC 到無線的切換過程中,基于三個基礎步驟,在執(zhí)行上層也逐步孵化出前端領域下 發(fā)布類型 的概念。例如在當時存在著 Web 應用類型、前端資源類型、Weex 應用 等類型,底層系統(tǒng)針對每個細分的 發(fā)布類型,在整體的發(fā)布流程的細節(jié)對接上采取不同的發(fā)布部署方案,本地研發(fā)結(jié)合套件工具,形成線上、線下鏈路關聯(lián)統(tǒng)一的研發(fā)組合方式,更精細化地為每一種研發(fā)模式都提供最佳的研發(fā)部署體驗。
用戶從此之后就不再需要通過 Gitlab 的 webhook 觸發(fā)發(fā)布流程,"一鍵上線" 代表著前端工程體系又進入新的一個階段。
? 云構建
在上一個階段中,我們通過將編譯邏輯經(jīng)過中心化封裝的方式,借助 npm 的形式,形成了在研發(fā)編譯構建環(huán)節(jié)的規(guī)范描述。但是在部署上線環(huán)節(jié),構建器并未與線上部署流程進行串聯(lián),而不同的本地系統(tǒng)環(huán)境,同樣也會導致構建結(jié)果的不穩(wěn)定。
在當時伴隨著 Docker 技術的發(fā)展,我們思考通過 docker 快速啟停統(tǒng)一環(huán)境的能力來實現(xiàn)一個構建器運行的環(huán)境,通過 docker啟動的 container 容器來模擬執(zhí)行本地的編譯構建流程。同時利用統(tǒng)一的容器環(huán)境,結(jié)合前文介紹的遷移之后的 Gitlab 提供的 commit等版本標識信息,能在最大程度上保證構建內(nèi)容的穩(wěn)定統(tǒng)一。
經(jīng)過了一段時間的摸索,通過在體系內(nèi)經(jīng)歷了例如 建立前端 docker 容器集群、串聯(lián)打通容器與應用的網(wǎng)絡通道、建設構建任務調(diào)度策略邏輯、借助 redis 打通 docker 容器運行日志等技術環(huán)節(jié)的驗證探索之后,我們基于容器技術搭建起來了在前端持續(xù)集成領域的 云構建 系統(tǒng)。
在通過淘系的 NodeJS 應用框架 midwayjs 完成線上構建能力搭建的同時,在業(yè)務側(cè)我們也在逐步建立更友好、完善的線上構建業(yè)務邏輯。借助在線上發(fā)布流程時調(diào)用 云構建 服務,在整個構建任務的執(zhí)行流程中,串聯(lián)起來了 構建器、倉庫、用戶 三者的業(yè)務關系。在這個關系網(wǎng)下,我們建立了完善的任務執(zhí)行情況的調(diào)度管理,能完整記錄構建器任務執(zhí)行的具體情況。
在構建器視角下,可以看到構建器針對不同倉庫的執(zhí)行情況,有著完整的運行日志與構建時間、構建錯誤記錄,方便用戶針對構建器進行錯誤排查以及性能優(yōu)化。而針對構建器的迭代更新,構建器開發(fā)者可以針對用戶進行灰度范圍劃分設置,在版本更迭時通過完整的灰度流程保證上線的穩(wěn)定覆蓋。在構建器發(fā)布過程中如有問題,立即取消灰度進行處理。通過這樣的模式,最大化地降低發(fā)布版本的風險。在針對橫向覆蓋較大的場景下,完整的灰度發(fā)布機制起著舉足輕重的作用。
用戶在研發(fā)過程中需要將本地構建代碼推送到倉庫的這個環(huán)節(jié)也從此變成了歷史,在源碼完成開發(fā)之后,直接提交源碼到倉庫中,執(zhí)行發(fā)布任務的同時,云構建系統(tǒng)會自動構建出穩(wěn)定、統(tǒng)一的構建產(chǎn)出結(jié)果。
? 門神
在完成在完成項目的編譯、壓縮過程之后,看似已經(jīng)走到部署環(huán)節(jié)的前端資源,在面對不斷復雜起來的業(yè)務場景下,實際仍然存在著許多隱蔽的問題,而以往通過人工檢查的方式已經(jīng)逐漸無法保障上線資源的可靠性。在這樣的背景下,也需要一個流程化、規(guī)范化的方式進行系統(tǒng)干預、檢測,做好發(fā)布資源的最后一道防線。
與 云構建 類似,基于 NodeJS 搭建線上資源檢查運行環(huán)境,通過將檢查邏輯也進一步抽象化,同樣以 npm 的形式進行承載抽象出 檢查器 的概念。在用戶資源完成所有的前置處理后,再進入到門神系統(tǒng)并行檢查任務的執(zhí)行,再完成例如 資源地址、敏感詞、代碼注釋 等等檢查之后,通過不同分級的檢查結(jié)果,反饋用戶相應的處理方式。作為上線前資源的最后一道關卡。系統(tǒng)取名 門神 寓意保障每一次的發(fā)布資源的上線基本質(zhì)量和安全。
通過門神自動化的方式,用戶不再需要在上線前"火眼金睛"檢驗各種無法通過常規(guī)編譯工具發(fā)現(xiàn)的問題,輕松上線。
? 能力開放
一方面隨著體系內(nèi)前端工程領域不斷的發(fā)展,不斷有更多的研發(fā)解決方案隨著業(yè)務場景的不斷發(fā)展涌現(xiàn)出來,另一方面隨著體系內(nèi) 研發(fā)部署平臺、云構建、門神 逐步成為集團前端研發(fā)場景的實施規(guī)范和基礎設施。在這個背景下,底層能力得到了進一步抽象開放的契機,上層的業(yè)務體系可以根據(jù)自身的業(yè)務情況,通過借助成熟的底層工程中臺能力搭建屬于自身業(yè)務體系的前端研發(fā)流程。
例如從阿里體系視角看,不同的投放客戶端,不同的資源組織形式,借助通用抽象化的底層工程能力,最終讓每一個業(yè)務場景的開發(fā)者都能擁有在項目業(yè)務場景下的最佳研發(fā)體驗。
? 貝搭建平臺
如何設計阿里經(jīng)濟體都在用的搭建服務—天馬
除了常規(guī)的項目研發(fā),在電商體系下,特別是在營銷場景下存在著需要快速生產(chǎn)頁面的需求。在這樣的業(yè)務場景背景下,孵化出來了通過模塊生成頁面的搭建平臺。通過將頁面進行重新劃分,分割成 頁面骨架和 頁面模塊 的方式,通過前端同學開發(fā)這些頁面元素,完成開發(fā)后進行組合搭配,同時打通業(yè)務數(shù)據(jù)流,實現(xiàn)快速搭建頁面的能力。
前端研發(fā)同學在完成本地模塊開發(fā)后,將模塊資源進行發(fā)布到線上,在搭建系統(tǒng)中進行頁面組裝和上下文注入預覽后,完成頁面級別發(fā)布。在底層同樣借助 NodeJS 實現(xiàn)的源站系統(tǒng)來承載 CDN 內(nèi)容的分發(fā)回源,提供億萬用戶的訪問預覽。這套體系經(jīng)過幾代的發(fā)展更迭,已經(jīng)成為當下前端研發(fā)的最核心場景之一。
大致從 15 年開始的幾年時間里,伴隨著技術的發(fā)展,淘系前端的研發(fā)體系從最初的本地工具、研發(fā)部署平臺作為排頭兵,逐步發(fā)展成線上線下的體系化專業(yè)解決方案。在保證前端角色的研發(fā)基礎體驗不斷突破升級的同時,企業(yè)化規(guī)模化的前端工程建設將日常零散的研發(fā)形式不斷推向更體系化的、高效率的、可擴展的 研發(fā)模式,同時也為后續(xù)更上層的研發(fā)部署模式的突破和升級打下堅實的基礎。
未來時代
在逐步成熟的工程體系之上,在最近的幾年時間內(nèi),我們也在思考面對 研發(fā)提效 這件事情上,是否還能有更突破的、面向未來的解法。隨著許多內(nèi)部產(chǎn)品不斷地改造和迭代,也不斷浮現(xiàn)出了星星之火可以燎原的方向和模式。
? D2C
imgcook 項目最初起源于可視化搭建,到目前外部看到的研發(fā)模式也是經(jīng)歷了不斷的改進、變化。在整個的研發(fā)模式變化中,從外部的視角大致經(jīng)歷幾個階段 :
- 第一階段: 當時的用戶的使用方式是通過頁面元素的拖拽進行頁面搭建,產(chǎn)出源代碼之后進行發(fā)布上線。
- 第二階段: 通過建立圖像掃描引擎進行像素掃描布局,同時接入 sketch 等視覺設計工具,自動的將設計稿進行轉(zhuǎn)換,這個階段前端用戶的研發(fā)方式式就開始變化成了將視覺稿進行上傳到平臺處理進行代碼轉(zhuǎn)換;
- 第三階段: 在當下的第三個階段,平臺正通過深度學習等人工智能技術來提效圖像代碼轉(zhuǎn)換的能力,與此同時在平臺端完善基礎研發(fā)鏈路的打通。內(nèi)部的研發(fā)模式也正逐步切換到了在設計、代碼的工作臺中進行操作,實現(xiàn)一站式研發(fā)、上線的操作體驗。
目前 D2C 能力逐步在智能化還原組件、表單、模塊、頁面的研發(fā)場景中逐步得到驗證并收獲一定的成果。
? IDE
在最近的一年時間,我們也逐步投入到了新的 IDE 方向建設中,期望通過 IDE 的平臺能力來孵化新的更高效的研發(fā)模式。
? 外部趨勢
從外部視角來看,可以看到有兩個趨勢浮出水面。一個是 IDE 領域相關的創(chuàng)業(yè)公司逐漸浮現(xiàn)出來,出現(xiàn)了許多相關的創(chuàng)業(yè)明星公司,例如有 Eclipse 體系下的 theia ,通過兼容 VSCode 接口實現(xiàn)的 coder,以及研發(fā)編輯領域的行業(yè)新秀 codesandbox;另一個是云廠商的加入,AWS 收購 Cloud9、騰訊收購 Coding、Azure 提供 Codespace 服務。
在編輯器、Docker 等技術的不斷發(fā)展成熟之下,各個 IDE 相關服務廠商都希望能借助集成研發(fā)環(huán)境的能力來找到研發(fā)效率、體驗提升的機會,從而抓住用戶的痛點,擴張產(chǎn)品市場。
? 內(nèi)部體系
前端研發(fā)模式隨著不斷的分化、發(fā)展,涌現(xiàn)出越來越多的工具、服務。當下工具、服務的形式也不單單只是前文提到的命令行終端工具,或者說終端工具也逐漸成為了富交互的工具、服務的啟動入口。同時一種業(yè)務研發(fā)模式往往也需要串聯(lián)到不同體系、不同團隊提供的研發(fā)工具、服務。舉一個例子,例如當下支付寶小程序的研發(fā),除了基礎的編譯服務、預覽服務之外,需要用到模擬器、調(diào)試器、真機調(diào)試等等服務。
支付寶小程序其實是內(nèi)部很多場景的一個縮影,支付寶小程序當下的解法其實是借助 Electron 平臺打造了一款本地的 IDE 研發(fā)工具。在這樣的背景之下,體系內(nèi)去年也開始了 IDE 底層體系 的搭建。期望能通過一套 IDE 底層實現(xiàn)線上、線下的基礎 IDE 解決方案。
借助 IDE 底層插件機制,淘系也孵化出自己的 IDE 集成研發(fā)工具,例如前文提到的 D2C 、支付寶小程序、serverless 等場景都在緊鑼密鼓的進行內(nèi)部拓展和使用改進。我們通過 IDE 及 IDE 的插件體系,一方面借助 VSCode 的生態(tài)完善基本研發(fā)體驗,另一方面通過插件在 VSCode 能力范圍之上擴展的插件 UI 能力來串聯(lián)起單個項目鏈路上所涉及到的所有的工具、服務。
與以往的流程的不同的是,除了將線上的發(fā)布部署流程進行串聯(lián)整合,研發(fā)同學在當下所有的在研發(fā)過程的操作包括 研發(fā)編碼、調(diào)試預覽、部署流程 都在統(tǒng)一的研發(fā) IDE 中有機的銜接起來,直接通過研發(fā)面板完成所有操作。這是我們?yōu)槲磥砺裣碌囊活w種子,正在慢慢發(fā)芽。
整篇答案其實從一個在體系內(nèi)的員工角度向大家介紹了關于淘系前端研發(fā)部署相關的一些歷程,當下的研發(fā)模式我們也在日赴夜繼的探索突破,最后介紹下團隊做的事情。
One More Thing
我們是 淘系前端團隊-工程中臺團隊 ,作為淘系前端及阿里集團前端的前端研發(fā)的基礎設施,目前在做前端工程相關的體系建設,主要有幾塊事情
1. 下一代前端研發(fā)模式: 通過自建阿里 IDE 核心底層 KAITIAN,借助底層兩端一致、可視化插件體系等基礎能力深度整合集成現(xiàn)有研發(fā)服務資產(chǎn),搭建當下及未來研發(fā)模式,新的領域等你來架構
2. 前端工程基礎服務:基于 NodeJS、Docker 等能力建設前端研發(fā)持續(xù)集成流程,百萬級別任務量等你來優(yōu)化、挑戰(zhàn)
3. 大規(guī)模 CDN 源站: 基于 NodeJS 實現(xiàn)集團核心 CDN 會員核心服務,大促基礎設施,億級流量等你來"開飛機換引擎"