摘要:本篇文章主要介紹騰訊團(tuán)隊(duì)從到在工程化的思考和實(shí)踐。的全稱是前端工作流,致力于提升研發(fā)效率和規(guī)范的工程化解決方案。最后騰訊團(tuán)隊(duì)的工程化解決方案已經(jīng)開(kāi)源主頁(yè)如果對(duì)您的團(tuán)隊(duì)或者項(xiàng)目有幫助,請(qǐng)給個(gè)支持一下哈
本篇文章主要介紹騰訊IVWEB團(tuán)隊(duì)從0到1在工程化的思考和實(shí)踐。feflow的全稱是Front-end flow(前端工作流),致力于提升研發(fā)效率和規(guī)范的工程化解決方案。愿景是通過(guò)feflow,可以使項(xiàng)目創(chuàng)建、開(kāi)發(fā)、構(gòu)建、規(guī)范檢查到最終項(xiàng)目上線的整個(gè)過(guò)程更加自動(dòng)化和標(biāo)準(zhǔn)化。
要解決的問(wèn)題項(xiàng)目的目錄結(jié)構(gòu)按約定生成
團(tuán)隊(duì)有一套開(kāi)發(fā)規(guī)范進(jìn)行約束
支持多種類型的構(gòu)建,包括Fis構(gòu)建和webpack構(gòu)建
團(tuán)隊(duì)內(nèi)部的代碼貢獻(xiàn)統(tǒng)計(jì)、離線包內(nèi)置App等
為了解決上述問(wèn)題,我們于17年2月底開(kāi)始投入工程化feflow工具的開(kāi)發(fā)和相關(guān)規(guī)范的制定,目前已經(jīng)研發(fā)出了 feflow 的 CLI 版本,后續(xù)會(huì)推出 GUI 版本。
架構(gòu)設(shè)計(jì)為了讓 feflow 的具有高可擴(kuò)展性,我們?cè)O(shè)計(jì)了4層結(jié)構(gòu),分別是:插件生態(tài)、內(nèi)核層、參數(shù)解析器和控制臺(tái)。除了貫穿整個(gè)開(kāi)發(fā)工作流的基礎(chǔ)命令選擇通過(guò)內(nèi)部插件內(nèi)置在CLI 的Core里面,其它非必要命令統(tǒng)一通過(guò)插件機(jī)制進(jìn)行擴(kuò)展。
另一方面,為了使得 feflow 能夠適用多種類型的項(xiàng)目。我們開(kāi)發(fā)了多種類型的業(yè)務(wù)腳手架,如:活動(dòng)模板、App H5模板、RN模板和業(yè)務(wù)組件模板。
執(zhí)行過(guò)程當(dāng)用戶在控制臺(tái)里面輸入某個(gè)命令。首先會(huì)通過(guò)CLI 的參數(shù)解析器,將這個(gè)命令解析成一個(gè)object對(duì)象,然后傳遞給CLI 的內(nèi)核。所有的命令都是通過(guò)內(nèi)核上下文提供的 register 函數(shù) 進(jìn)行注冊(cè)的,一方面內(nèi)核自身會(huì)讀取內(nèi)置插件 注冊(cè)的基礎(chǔ)命令,另一方面,內(nèi)核會(huì)讀取本地已經(jīng)安裝的外部插件注冊(cè)的命令。如果找到用戶輸入的命令則開(kāi)始執(zhí)行命令對(duì)應(yīng)的回調(diào)函數(shù)。
基礎(chǔ)命令設(shè)計(jì)# 初始化項(xiàng)目 $ feflow init # 本地開(kāi)發(fā) $ feflow dev # 代碼質(zhì)量檢查 $ feflow lint # 打包構(gòu)建 $ feflow build # 代碼發(fā)布 $ feflow publish # 安裝插件、腳手架等 $ feflow install package # 配置本地客戶端,如: npm 的源和 proxy $ feflow config
前面提到,CLI 的命令包含兩部分,分別是內(nèi)置在內(nèi)核里的基礎(chǔ)命令和外部插件提供的命令。那么外部插件要如何設(shè)計(jì)呢?
插件機(jī)制設(shè)計(jì) 插件實(shí)現(xiàn)原理這里有一個(gè)非常巧妙的設(shè)計(jì),通過(guò)使用node提供的module和vm模塊,可以通注入feflow全局變量來(lái)訪問(wèn)到cli的實(shí)例。從而能夠訪問(wèn)cli上的各種屬性,比如config, log和一些helper等。
loadPlugin(path, callback) { const self = this; return fs.readFile(path).then((script) => { const module = new Module(path); module.filename = path; module.paths = Module._nodeModulePaths(path); function require(path) { return module.require(path); } require.resolve = function(request) { return Module._resolveFilename(request, module); }; require.main = process.mainModule; require.extensions = Module._extensions; require.cache = Module._cache; // Inject feflow variable script = "(function(exports, require, module, __filename, __dirname, feflow){" + script + "});"; const fn = vm.runInThisContext(script, path); return fn(module.exports, require, module, path, pathFn.dirname(path), self); }).asCallback(callback); }命令注冊(cè):
命令需要以feflow.cmd.register進(jìn)行注冊(cè),比如:
feflow.cmd.register("deps", "Config ivweb dependencies", function(args) { console.log(args); // Plugin logic here. });
說(shuō)明:
register有3個(gè)參數(shù),第一個(gè)是子命令名稱,第二個(gè)是命令描述說(shuō)明信息,第三個(gè)是對(duì)應(yīng)的子命令執(zhí)行邏輯函數(shù)。
feflow會(huì)將命令行參數(shù)args解析成Object對(duì)象,傳遞給插件處理函數(shù)
配置可以通過(guò)feflow.version獲取當(dāng)前feflow的版本,feflow.baseDir 獲取feflow跟目錄(在用戶目錄下的.feflow),通過(guò)feflow.pluginDir 獲取插件目錄
日志通過(guò)feflow.log來(lái)進(jìn)行相關(guān)命令行日志輸出
const log = feflow.log; log.info() ? // 提示日志,控制臺(tái)中顯示綠色 log.debug() ? // 調(diào)試日志, 命令行增加--debug可以開(kāi)啟,控制臺(tái)中顯示灰色 log.warn() ? // 警告日志,控制臺(tái)中顯示黃色背景 log.error() ? // 錯(cuò)誤日志,控制臺(tái)中顯示紅色 log.fatal() ? // 致命錯(cuò)誤日志,,控制臺(tái)中顯示紅色安裝
插件開(kāi)發(fā)完成后,可以通過(guò) feflow 提供的 install 命令安裝插件。安裝的插件會(huì)放置在本地客戶端 ~/.feflow/node_modules 文件夾下,并且寫(xiě)入到 ~/.feflow/package.json 中
$ feflow install feflow-plugin-xxx // 安裝某個(gè)插件
之后每次運(yùn)行命令時(shí),便會(huì)從本地加載插件所注冊(cè)的命令
全量更新和增量更新當(dāng)CLI發(fā)布了一個(gè)新的版本,可能我們會(huì)廢棄掉某些功能或者提供了新功能。這個(gè)時(shí)候如果用戶依然使用的是舊版本,由于某些服務(wù)已經(jīng)廢棄掉了則會(huì)報(bào)錯(cuò)。在這種新舊版本不兼容的情況下,如何強(qiáng)制用戶進(jìn)行CLI的升級(jí)呢?需要在運(yùn)行命令之前檢查本地的CLI是否和遠(yuǎn)程提供的新版本是否兼容。在新舊版本不兼容時(shí),會(huì)強(qiáng)制全量更新。如何判斷當(dāng)前用戶安裝的本地版本和遠(yuǎn)程最新版本是否兼容呢?
這里非常巧妙的運(yùn)用了一下 npm 的 registry機(jī)制,每次發(fā)布新版本,我們會(huì)在 package.json 里面新增一個(gè)自定義字段 compatibleVersion,它的值是一個(gè) semver 的版本號(hào)。本地檢查時(shí),會(huì)讀取本地已經(jīng)安裝的版本和遠(yuǎn)程最新的版本進(jìn)行比較,看看是否滿足 compatibleVersion 的要求。如果不滿足,則會(huì)自動(dòng)運(yùn)行 npm install feflow-cli 到最新的版本。
"configs": { "compatibleVersion": ">=0.13.0" },
對(duì)于插件,采取的是增量更新機(jī)制。每個(gè)發(fā)布到 npm 上的插件的package.json 中同樣會(huì)有上面的這個(gè)字段,對(duì)于本地安裝的不兼容的插件列表,會(huì)采取增量更新。
多類型腳手架的架構(gòu)設(shè)計(jì)項(xiàng)目拷貝存在的問(wèn)題顯而易見(jiàn),大致有以下三個(gè)方面:
容易出錯(cuò);一旦某個(gè)關(guān)鍵文件拷貝丟失或者錯(cuò)誤,很可能需要耗費(fèi)半天到一天的時(shí)間排查環(huán)境問(wèn)題。
不同場(chǎng)景下對(duì)目錄結(jié)構(gòu)要求不同;平時(shí)開(kāi)發(fā)過(guò)程中,工程通常會(huì)分為運(yùn)營(yíng)活動(dòng)、Hybrid業(yè)務(wù)、入口級(jí)別的項(xiàng)目(對(duì)性能和體驗(yàn)有極致和苛刻的要求)。需要基于RN或者Node.js的首屏直出,還有常用的業(yè)務(wù)組件等的開(kāi)發(fā)。
新的Feature和BugFix難以同步;某個(gè)同學(xué)開(kāi)發(fā)過(guò)程中增加的新方法或者解決的bug很難傳遞給其它同學(xué)并且沉淀成經(jīng)驗(yàn)積累下來(lái)。
社區(qū)里面提供了完美的Yeoman解決方案,它是為了自動(dòng)化項(xiàng)目的創(chuàng)建而生。Yeoman創(chuàng)建項(xiàng)目包括以下幾個(gè)階段:
initializing: 初始化一些狀態(tài)之類的,通常是和用戶輸入的 options 或者 arguments 打交道
prompting: 和用戶交互的時(shí)候(命令行問(wèn)答之類的)調(diào)用
configuring: 保存配置文件(如 .babelrc 等)
writing: 生成模板文件
install: 安裝依賴
end: 結(jié)束部分,初始代碼自動(dòng)提交
我們只需要繼承Yeoman的Generator類做模板定制化,基于Yeoman的腳手架設(shè)計(jì)思路應(yīng)該如下圖所示:
當(dāng)開(kāi)發(fā)者輸入 feflow init 命令時(shí),開(kāi)發(fā)者會(huì)告訴CLI需要?jiǎng)?chuàng)建哪一種類型的項(xiàng)目,CLI收到命令后。從本地已經(jīng)安裝的Yeoman腳手架里面選擇某種類型的模板。然后,CLI會(huì)調(diào)用Gitlab API在遠(yuǎn)程創(chuàng)建倉(cāng)庫(kù)并且授予開(kāi)發(fā)者master權(quán)限。接下來(lái),會(huì)根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景需要,自動(dòng)化申請(qǐng)一些打點(diǎn)信息,常見(jiàn)的如離線包id,監(jiān)控告警id等等。之后,在本地目錄生成代碼并且安裝項(xiàng)目依賴的npm包,最后將本次初始化生成的所有代碼自動(dòng)提交到遠(yuǎn)程Git倉(cāng)庫(kù)。
多類型主流構(gòu)建支持為了讓feflow 支持多種類型的構(gòu)建環(huán)境,比如 Fis3 和 webpack,或者前不久剛推出的號(hào)稱零配置成本的 Parcel 構(gòu)建。在每個(gè)項(xiàng)目的跟目錄會(huì)放置一份配置文件,名稱為 feflow.json。它的配置可能是這樣的:
{ "builderType": "builder-webpack3", "builderOptions": { "moduleName": "mobile", "bizName": "category", "minifyHTML": true, "minifyCSS": true, "minifyJS": true, "usePx2rem": true, "remUnit": 100, "remPrecision": 8, "inject": true, "port": 8001 } }
builderType為構(gòu)建的npm包,builderOptions為構(gòu)建的參數(shù)配置。
最后騰訊IVWEB團(tuán)隊(duì)的工程化解決方案feflow已經(jīng)開(kāi)源:Github主頁(yè):https://github.com/feflow/feflow
如果對(duì)您的團(tuán)隊(duì)或者項(xiàng)目有幫助,請(qǐng)給個(gè)Star支持一下哈~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107614.html
摘要:之后,在本地目錄生成代碼并且安裝項(xiàng)目依賴的包,最后將本次初始化生成的所有代碼自動(dòng)提交到遠(yuǎn)程倉(cāng)庫(kù)。按照城市評(píng)選,分別評(píng)選明日之子僅限男性參加和閃亮女神僅限女性參加。 背景: 隨著開(kāi)發(fā)團(tuán)隊(duì)規(guī)模不斷發(fā)展壯大,在人員增加的同時(shí)也帶來(lái)了協(xié)作成本的增加,業(yè)務(wù)項(xiàng)目越來(lái)越多,類型也各不相同。常見(jiàn)的類型有組件類、活動(dòng)類、基于React+redux的業(yè)務(wù)項(xiàng)目、RN項(xiàng)目、Node.js項(xiàng)目等等。如果想要對(duì)每...
摘要:當(dāng)下最流行的模塊打包器于年月日正式發(fā)布版本,代號(hào)。從官方的發(fā)布日志來(lái)看本次大版本更新帶來(lái)了很多新特性更新和改善,這將會(huì)讓的配置更加簡(jiǎn)單。本文,筆者將會(huì)全面介紹的新特性及實(shí)踐。只支持模塊,目前處于試驗(yàn)階段。 導(dǎo)語(yǔ): webpack是一個(gè)JS應(yīng)用打包器, 它將應(yīng)用中的各個(gè)模塊打成一個(gè)或者多個(gè)bundle文件。借助loaders和plugins,它可以改變、壓縮和優(yōu)化各種各樣的文件。它的輸入...
摘要:的編譯構(gòu)建上一篇文章詳解中介紹了基于事件流編程,是個(gè)高度的插件集合,整體介紹了的編譯流程。本文將單獨(dú)聊一聊最核心的部分,編譯構(gòu)建。的編譯重要的構(gòu)建節(jié)點(diǎn)的構(gòu)建中總會(huì)經(jīng)歷如下幾個(gè)事件節(jié)點(diǎn)。 webpack的編譯&構(gòu)建 上一篇文章webpack詳解中介紹了webpack基于事件流編程,是個(gè)高度的插件集合,整體介紹了webpack 的編譯流程。本文將單獨(dú)聊一聊最核心的部分,編譯&構(gòu)建。 web...
摘要:其中負(fù)載均衡那一節(jié),基本上是參考的權(quán)威指南負(fù)載均衡的內(nèi)容。開(kāi)發(fā)指南讀了一半,就是看這本書(shū)理解了的事件循環(huán)。哈哈創(chuàng)京東一本騙錢的書(shū)。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由騰訊IVWEB團(tuán)隊(duì) 發(fā)表于云+社區(qū)專欄作者:link 2014年一月以來(lái),自己接觸web前端開(kāi)發(fā)已經(jīng)兩年多了,記錄一下自己前端學(xué)習(xí)路上看過(guò)的,以及道聽(tīng)途說(shuō)的一些書(shū),基本上按照由淺入深來(lái)介紹...
摘要:其中負(fù)載均衡那一節(jié),基本上是參考的權(quán)威指南負(fù)載均衡的內(nèi)容。開(kāi)發(fā)指南讀了一半,就是看這本書(shū)理解了的事件循環(huán)。哈哈創(chuàng)京東一本騙錢的書(shū)。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由騰訊IVWEB團(tuán)隊(duì) 發(fā)表于云+社區(qū)專欄作者:link 2014年一月以來(lái),自己接觸web前端開(kāi)發(fā)已經(jīng)兩年多了,記錄一下自己前端學(xué)習(xí)路上看過(guò)的,以及道聽(tīng)途說(shuō)的一些書(shū),基本上按照由淺入深來(lái)介紹...
閱讀 3205·2021-09-06 15:02
閱讀 2250·2019-08-30 15:48
閱讀 3448·2019-08-29 11:08
閱讀 3291·2019-08-26 13:55
閱讀 2453·2019-08-26 13:35
閱讀 3168·2019-08-26 12:11
閱讀 2607·2019-08-26 11:48
閱讀 891·2019-08-26 11:42