摘要:自動化接入和升級方案通過命令行工具提供一鍵接入升級能力,同時集成到團隊腳手架中,大大降低了工程接入和維護的成本。原始代碼經過解析器的解析,在管道中逐一經過所有規則的檢查,最終檢測出所有不符合規范的代碼,并輸出為報告。
引言
代碼規范是軟件開發領域經久不衰的話題,幾乎所有工程師在開發過程中都會遇到,并或多或少會思考過這一問題。隨著前端應用的大型化和復雜化,越來越多的前端工程師和團隊開始重視 JavaScript代碼規范。得益于前端開源社區的繁盛,當下已經有幾種較為成熟的 JavaScript 代碼規范檢查工具,包括 JSLint、JSHint、ESLint、FECS 等等。本文主要介紹目前較為通用的方案——ESLint,它是一款插件化的 JavaScript 代碼靜態檢查工具,其核心是通過對代碼解析得到的 AST(Abstract Syntax Tree,抽象語法樹)進行模式匹配,定位不符合約定規范的代碼。
ESLint 的使用并不復雜。依照 ESLint 的文檔安裝相關依賴,可以根據個人/團隊的代碼風格進行配置,即可通過命令行工具或借助編輯器集成的 ESLint 功能對工程代碼進行靜態檢查,發現和修復不符合規范的代碼。如果想降低配置成本,也可以直接使用開源配置方案,例如eslint-config-airbnb或eslint-config-standard。
對于獨立開發者,或者執行力較強、技術場景較為單一的小型團隊而言,直接使用 ESLint 及其生態提供的一些標準方案,可以用較低成本來實現 JavaScript 代碼規范的落地。如果再搭配一些輔助工具(例如 husky 和 lint-staged),整個流程會更加順暢。但對于數十人的大型前端團隊來說,面向數百個前端工程,規模化地應用統一的 JavaScript 代碼規范,問題就會變得較為復雜。如果直接利用現有的開源配置方案,可能會使工作事倍功半。
問題分析規模化應用統一的 ESLint 代碼規范,會涌現各類問題,根源在于大型團隊和小團隊(或獨立開發者)的差異性:
技術層面上:
技術場景更加廣泛:對于大型團隊,其開發場景一般不會局限在傳統 Web 領域內,往往還會涉及 Node.js、React Native、小程序、桌面應用(例如 Electron)等更廣泛的技術場景。
技術選型更加分散:團隊內工程技術選型往往并不統一,如 React/Vue、JavaScript/TypeScript 等。
工程數量的增加和工程方案離散化導致 ESLint 方案的復雜度提升:這樣會進一步增加工程接入成本、升級成本和方案維護成本。
在團隊層面,隨著人員的增加和組織結構的復雜化:
人員風格差異性更大、溝通協調成本更高。
方案宣導更難觸達,難以保證規范執行的落實。
執行狀況和效果難以統計和分析。
因為存在諸多差異,我們在設計具體方案時,需要考慮和解決更多問題,以保證規范的落實。針對上述分析,我們梳理了以下需要解決的問題:
如何制定統一的代碼規范和對應的 ESLint 配置?
場景支撐:如何實現對場景差異的支持?如何保證不同場景間一致部分(例如 JavaScript 基礎語法)的規范一致性?
技術選型支撐:如何在支撐不同技術選型的前提下,保證基礎規則(例如縮進)的一致性?
可維護性:具體到規則配置上,能否提升可復用性?在方案升級迭代時成本是否可控?
如何保證代碼規范的執行?
人員的增加和組織結構的復雜化,會導致基于管理的執行把控失效,這種情況應該如何保證代碼規范的執行質量?
如何降低應用成本?
在工程數量增加、工程方案離散化的情況,降低方案的接入、升級和執行成本能節約大量的人力,同時也有利于方案落地推進。
如何及時了解規范應用狀況和效果?
解決方案為了能在團隊內實現 JavaScript 代碼規范的統一,在分析和思考團隊規模化應用存在的問題后,我們設計了一套完整的技術解決方案。該方案包括多場景統一的 ESLint 規則配置、代碼集成交付檢查、自動化接入工具、執行狀況監測分析等四個模塊。通過各個模塊協調配合,共同解決上文提出的問題,在降低維護成本、提升執行效率的同時,也保障了代碼規范的統一。
整體方案的設計如下圖所示:
多場景統一的 JavaScript 規范:該模塊是整個方案的核心,借助 ESLint 的特性,通過分層分類的結構設計,在保證基礎規則一致性的同時,實現了對不同場景、技術選型的支撐。
代碼集成交付檢查:該模塊是方案落地執行的保障,將代碼靜態檢查集成到持續交付工作流中。具體設計實現上,在保證交付質量的同時,也通過定制集成檢查工具降低了開發者的應用執行成本。
自動化接入和升級方案:通過命令行工具提供“一鍵”接入/升級能力,同時集成到團隊腳手架中,大大降低了工程接入和維護的成本。
執行狀況監測分析:通過對工具運行和代碼集成交付檢查過程進行埋點、檢查結果收集和分析,了解方案的應用狀態和效果。
方案實現上文中提出的問題,通過各模塊的協調配合能夠得到有效地解決,但具體到各個模塊的實現,仍然需要進一步深入思考,以設計出更加合理的實現方案。本章將對方案的四個核心模塊進行詳細介紹。
通用 ESLint 配置方案這一模塊主要借助 ESLint 的基礎特性,采用分層分類的結構設計,提供多場景、多技術方案的通用配置方案,并使方案具備易維護、易擴展的特性。
ESLint 特性簡介在進行 ESLint 配置方案設計前,我們先看一下 ESLint 的一些特點。
1.插件化
下圖簡單地描述了 ESLint 的工作過程:
ESLint 的能力更像一個引擎,通過提供的基礎檢測能力和模式約束,推動代碼檢測流程的運轉。原始代碼經過解析器的解析,在管道中逐一經過所有規則的檢查,最終檢測出所有不符合規范的代碼,并輸出為報告。借助插件化的設計,不但可以對所有的規則進行獨立的控制,還可以定制和引入新的規則。ESLint 本身并未和解析器強綁定,我們可以使用不同的解析器進行原始代碼解析,例如可以使用 babel-eslint 支持更新版本、不同階段的 ES 語法,支持 JSX 等特殊語法,甚至可以借助 @typescript-eslint/parser 支持 TypeScript 語言的檢查。
2.配置能力全面、可層疊、可共享
ESLint 提供了全面、靈活的配置能力,可以對解析器、規則、環境、全局變量等進行配置;可以快速引入另一份配置,和當前配置層疊組合為新的配置;還可以將配置好的規則集發布為 npm 包,在工程內快速應用。
3.社區生態較為成熟
開源社區中基于 ESLint 的項目非常多,既有針對各種場景、框架的插件,也有各種 ESLint 規則配置方案,基本可以涵蓋前端開發的所有場景。
規范配置方案設計基于 ESLint 的插件化、可層疊配置特性,以及面向各種場景、框架的開源方案,我們設計了如下圖所示的 ESLint 配置架構:
該配置架構采用了分層、分類的結構,其中:
基礎層:制定統一的基礎語法和格式規范,提供通用的代碼風格和語法規則配置,例如縮進、尾逗號等等。
框架支撐層(可選):提供對通用的一些技術場景、框架的支持,包括 Node.js、React、Vue、React Native等;這一層借助開源社區的各種插件進行配置,并對各種框架的規則都進行了一定的調整。
TypeScript 層(可選):這一層借助?typescript-eslint,提供對 TypeScript 的支持。
適配層(可選):提供對特殊場景的定制化支持,例如 MRN(美團內部的 React Native 定制化方案)、配合 prettier 使用、或者某些團隊的特殊規則訴求。
具體的實際項目中,可以靈活的選擇各層級、各類型的搭配,獲得和項目匹配的 ESLint 規則集。例如,對于使用 TypeScript 語言的 React 項目,可以將基礎層、框架層的 React 分支、以及 TypeScript 支撐層的 React 分支層疊到一起,最終形成適用于該項目的 ESLint 配置。如果項目不再使用 TypeScript 語言,只需要將?ts-react?這一層去掉即可。
最終,形成了如下所示的 ESLint 配置集:
考慮到維護、升級和應用成本,我們最終選擇將所有配置放到一個 npm 包中,而不是每種類型分別設置。仍以使用 TypeScript 語言的 React 項目為例,只需在工程中進行如下配置:
// 需要安裝 typescript、eslint-plugin-react、@typescript-eslint 等插件 module.exports = { root: true, extends: [ // 因為基礎層是必備的,所以框架層默認引入了對應的基礎層,不需再多帶帶引入 eslintrc.base.js "eslint-config-xxx/eslintrc.react.js", "eslint-config-xxx/eslintrc.typescript-react.js" ] }
這種通過分層、分類的結構設計,還有利于后期的維護:
對基礎層的修改,只需修改一處即會全局生效。
對非基礎層某一部分的調整不會產生關聯性的影響。
如需擴展對某一類型的支持,只需關注這一類型的特殊規則配置。
眾所周知,TypeScript 類型的項目使用 TSLint 進行代碼檢查,也是一種簡單、便捷的方案。但在本方案中我們依舊選擇了:eslint?+?@typescript-eslint/parser?+?@typescript-eslint/eslint-plugin?的組合方案。主要有以下幾點原因:
ESLint 的規則配置更加詳細全面,覆蓋更加廣泛。
采用了分層分類的架構,能夠保證即使框架或語言不同,也能在基本語法、風格層面保持規則的一致性,這樣有利于團隊內不同技術選型項目的風格統一。
@typescript-eslint 方案持續迭代,問題響應非常迅速,對 TSLint 相關的規則基本提供了對等的實現。
根據最新消息,TypeScript在?2019 路線圖?中明確表明后續對 Lint 工具的支持和建設會以對 ESLint 進行適配的方式為主。
代碼集成檢查基于團隊對工程化基礎設施的建設,將代碼規范靜態檢查與開發工作流集成,保證代碼規范的落實。
通常而言,工程接入 ESLint 后,可以在開發的同時借助編輯器集成的 ESLint 檢查提示能力(例如 VSCode 的 ESLint 插件),實時發現和修改不符合規范的語法錯誤和風格問題。但這仍不能避免因一些主觀因素或疏漏造成的規范執行不到位,所以我們考慮在開發工作流的特定節點自動執行代碼靜態檢查,阻斷不合規范代碼的提交或交付。
集成靜態檢查的開發工作流節點有很多,我們主要參考以下兩種方案:
代碼提交檢查:在代碼 Commit 時,通過 githook 觸發 ESLint 檢查。其優點在于能實時響應開發者的動作,給出反饋,快速定位和修復問題;缺陷在于開發者可以主動跳過檢查。
代碼交付檢查:在代碼交付(借助 CI 系統的交付流程功能)時,在代碼檢測平臺中對代碼進行 ESLint 檢查,檢測不通過則阻斷交付。其優點在于能夠強制執行,可在線追蹤檢測報告;缺陷在于離開發者的開發環境太“遠”,開發者響應處理成本較高。
如果將兩者進行結合,可能會事半功倍,效果如下圖所示:
常用的代碼提交檢查方法一般是?husky?與?lint-staged 結合,在代碼 Commit 時,通過 githook 觸發對 git 暫存區文件的檢查。但考慮到團隊現有工程數量龐大、存在大量行數較多的文件,雖然?lint-staged?策略能夠降低部分成本,但仍稍顯不足。為此,我們對該方法進行優化,定制了本地代碼提交檢查工具?precommit-eslint,其核心特點是:
將增量檢查執行到代碼行這一粒度,支持 Warn 和 Error 兩個檢查級別。
只需將工具安裝為工程的依賴,無需任何配置。
減少了 pre-commit hook 中植入腳本的侵入性。
進行了執行狀況埋點和采集。
使用效果如下圖所示:
在美團,我們使用自主開發的 CI 系統,并在獨立部署的 Sonar 系統上定制化實現了相應規則,基本可以滿足訴求,這里就不再贅述。對于獨立的團隊,基于 ESLint 提供的工具,可以很容易的實現使用 Node 快速搭建一個代碼檢測服務或平臺,大家有興趣不妨一試。
自動化接入工具這個模塊主要通過 CLI 工具提供方案自動化接入的能力,降低工程接入和升級的成本。如果不借助自動化工具,在工程中接入上述方案還是有一定的工作量和復雜度的,大致步驟如下:
安裝 Eslint。
根據項目類型安裝對應的 ESLint 規則配置 npm 包。
根據項目類型安裝相關的插件、解析器等。
根據項目類型配置 .eslintrc 文件。
安裝代碼提交檢查工具。
配置 package.json。
測試及修復問題。
在這個過程中,特別需要注意依賴的版本問題:依賴之間的版本兼容性,例如?typescript?和?@typescript-eslint/parser?之間的兼容性;依賴對規則的支持性,比如某個版本的插件中去除了對某個規則的支持,但規則配置中仍然配置了該規則,此時配置就會失效。對于 ESLint 不熟悉的開發者而言,在配置的過程中都會或多或少遇到兼容性、解析異常、規則無效等問題,反復排查和定位問題會浪費大量的精力。
因此,在設計開發自動化接入工具時,我們綜合考慮了操作步驟、依賴版本、規則集和工程方案的兼容性,設計了如下的工作流程:
該工具流程簡單,不管什么開發場景和框架選型,繁瑣的接入流程都可以簡化為一條命令,需要配合工程方案升級時同樣如此。如下圖所示,執行該命令后項目就完成了 ESLint 的接入,使用統一的規則規范編碼,同是在代碼提交時自動進行增量檢查:
埋點與統計分析統計分析的主要目的是掌握方案應用執行狀況和效果,理論上應當支持工程和大盤兩個視角,如下圖所示:
執行情況分析其實并不復雜,核心是信息采集和分析。在本方案中,信息采集通過 precommit-eslint 工具實現:在 git commit 觸發本地代碼檢查后,腳本會把檢查結果(包括檢查是否通過、錯誤或警告信息的數量級別等)上報;信息的統計分析借助日志上報分析平臺實現,美團使用的是 CAT 平臺(如果團隊或公司沒有專門的平臺,可以在上文提到的代碼檢測服務平臺中實現這部分功能)。為了便于數據的聚合分析,我們將一次代碼提交檢查中出現的問題數量進行了分級:
檢查通過:檢查無代碼規范錯誤。
錯誤 1 級:檢查出代碼規范錯誤數量小于 10 個。
錯誤 2 級:檢查出代碼規范錯誤數量在 10 - 100 個之間。
錯誤 3 級:檢查出代碼規范錯誤數量在 100 - 1000 個之間。
錯誤 4 級:檢查出代碼規范錯誤數量大于 1000 個。
比如下圖中,201903 第一周的代碼提交檢查結果統計(綜合采樣率 0.2),很明顯,所有檢查失敗的提交中,錯誤數量在 10 個以內的占比最大,修復成本不高。
1.提交檢查異常分布(僅篩選檢查未通過信息)
2.提交檢查警告信息分析
除此之外,還可以對單一工程,在更細的時間粒度上去觀察提交檢查的執行情況。
效果質量主要分析工程質量的變化:一方面可以通過代碼檢查執行通過率變化趨勢、檢查結果分布去看持續的生產流程中,代碼質量是否有所提升;另一方面,由于代碼檢查采用增量模式,需要對工程代碼進行整體分析,得到工程整體的不規范代碼占比及變化趨勢,從而從工程維度分析判斷質量效果(涉及到權限相關問題,目前團隊中未采用工程分析的方法)。具體的分析會在方案應用效果中一并進行介紹。
方案應用除了上述整體方案外,為保證開發者使用更方便,我們還進行了一些配套工作:
持續維護升級:以每月一版的方式持續迭代升級,解決應用中的問題、規則爭議,以及支持新的規則或方案。
工程化集成:整套方案可以無縫接入到各個團隊的腳手架工具中,自動成為團隊的默認方案,在工程初始化階段即可完成接入。
官網建設:提供詳細的使用文檔,包括規則信息、接入方法,并且對每個版本提供規則、環境依賴、changeLog 等詳細說明。
常見使用問題:更新維護FAQ,幫助后續接入者快速查找并解決問題。
目前,該套方案已經接入美團外賣、餐飲平臺、閃購、榛果、金融等多個團隊,基于埋點統計分析,我們(基于2019年2月份最后一周統計數據分析,綜合采樣率0.2)得到了如下數據:
截止到2019年2月底,該方案已接入超過 200 個前端工程。
集成檢查(增量)每天執行接近 1000 次。
集成檢查(增量)平均每天檢查出錯誤約 20000-25000 處。
集成檢查代碼質量:平均通過率為 75.562%,錯誤 1 級的比率為 15.644%,在所有未通過檢查中占比 64.015%。
同時,我們持續統計上述數據的變化趨勢,跟蹤代碼質量提升效果,以2018年12月到2019年3月的數據為例(截止2019年3月第一周,以周為時間統計尺度):
從圖中可以看出,最近三個月檢查通過率整體呈上升趨勢,但 2019 年 1 月的第 2 周和第 3 周集成檢查通過率有明顯下降。分析項目信息發現,在 2019 年 1 月的第 2 周有一批新項目接入,代碼檢查規范檢查出幾十個錯誤。但整體來看,目前集成檢查通過率基本穩定在 75% - 80%,從變化趨勢看仍有上升空間。
方案實施之后,我們做了一個用戶調研,發現整體方案的運營正在發揮著正向的作用。一方面,在一定程度上提升了多人協作的效率,無論是共同維護一個工程還是在多個工程間切換,避免了代碼風格不一致帶來的可讀性成本和格式化風險;另一方面,會幫助大家發現和避免一些簡單的語法錯誤。
規劃和思考該方案已經穩定應用,除了現有功能,我們還在思考是否可以更進一步的優化,提供更豐富的能力。由此規劃了一些仍未落地的方向:
擴展支持 HTML 和 CSS 的代碼風格檢查:雖然近幾年前端框架、組件庫的建設一定程度上減少了業務開發中(尤其是中后臺業務)對 HTML 和 CSS 的需求,但是規范 HTML 和 CSS 的代碼風格仍是必要的。基于此,可以用同樣的思路將 HTML 和 CSS 的代碼靜態檢查方案集成到當前的方案中,不再局限于 JavaScript(或 TypeScript)。
進一步的封裝:目前整體方案會將所有依賴和配置暴露在工程內,如果將其完全封裝在一個工具內會更便于應用,但難點在于兼顧靈活性、對編輯器的支持等問題。
增加工程維度的代碼質量趨勢分析:目前代碼檢查策略是增量檢查,可以對接入的工程定期全量檢查,基于時間線分析工程的代碼質量變化趨勢。
進一步深入分析檢查結果和統計數據,發現一些潛在問題,為推動開發質量提升提供輔助,如:
統計開發者在工程中關閉或調整的規則,分析占比較高的規則被關閉的原因,進而調整規則或推動規則的執行。
統計分布檢查出錯誤的規則分布,梳理出最常出問題的代碼規則,發布對應的最佳實踐或手冊。
以上是美團外賣團隊在 ESLint 方案規模化應用過程中的一些實踐,歡迎大家提出建議,一起溝通交流。
作者簡介宋鵬,美團外賣事業部終端研發工程師。
團隊介紹美團外賣事業部終端團隊,負責的多個終端和平臺直接連接億萬用戶、數百萬商家和幾萬名運營與銷售,目標是在保障業務高穩定、高可用的同時,持續提升用戶體驗和研發效率。
在用戶方向上,構建了全鏈路的高可用體系,客戶端、Web前端和小程序等多終端的可用性在99%左右;跨多端高復用的局部動態化框架在首頁、廣告、營銷等核心路徑的落地,提升了30%的研發效率;
在商家方向上,從提高進程優先級、VoIP Push拉活、doze等方面進行保活定制,并提供了Shark、短鏈和Push等多條觸達通道,訂單到達率提升至98%以上;
在運營方向上,通過標準化研發流程、建設組件庫和Node服務以及前端應用的管理與頁面配置等提升10%的研發效率。
團隊有多個崗位正在招聘,歡迎加入我們,聯系郵箱 tech@meituan.com ,注明 “外賣終端團隊”。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106397.html
摘要:熱門文章我在淘寶做前端的這三年紅了櫻桃,綠了芭蕉。文章將在淘寶的三年時光折射為入職職業規劃招聘晉升離職等與我們息息相關的經驗分享,值得品讀。 showImg(https://segmentfault.com/img/remote/1460000018739018?w=1790&h=886); 【Alibaba-TXD 前端小報】- 熱門前端技術快報,聚焦業界新視界;不知不覺 2019 ...
摘要:熱門文章我在淘寶做前端的這三年紅了櫻桃,綠了芭蕉。文章將在淘寶的三年時光折射為入職職業規劃招聘晉升離職等與我們息息相關的經驗分享,值得品讀。 showImg(https://segmentfault.com/img/remote/1460000018739018?w=1790&h=886); 【Alibaba-TXD 前端小報】- 熱門前端技術快報,聚焦業界新視界;不知不覺 2019 ...
摘要:最佳實踐一個文件一個組件。,這是包含的是無副作用的純函數式計算狀態操作的函數。,的啟動腳本,啟動開發模式,項目打包,運行單元測試等等。每次代碼推送到之前也會執行所有單元測試用例,全部通過才可以繼續推送。,首次安裝依賴包之后生成的文件。 前段時間 React license 的問題鬧的沸沸揚揚,搞得 React 社區人心惶惶,好在最終 React 團隊聽取了社區意見把 license 換...
摘要:近期在按照業務劃分項目時,我們組被分了好多的項目過來,大量的是基于的,也是我們組持續在使用的語言。部署環境強依賴本地,因為需要在本地建立倉庫的臨時目錄,并經過多次的方式完成部署上線的操作。 近期在按照業務劃分項目時,我們組被分了好多的項目過來,大量的是基于 Node.js 的,也是我們組持續在使用的語言。 現有流程中的一些問題 在維護多個項目的時候,會暴露出一些問題: 如何有效的使用...
閱讀 2749·2021-11-25 09:43
閱讀 2110·2021-11-18 13:25
閱讀 4571·2021-09-22 15:52
閱讀 1869·2021-09-22 15:49
閱讀 2215·2019-08-30 15:54
閱讀 3010·2019-08-29 17:13
閱讀 2317·2019-08-29 16:54
閱讀 2258·2019-08-29 12:58