微店前端工程化的迭代史

文章同步在:github.com/hoperyy/blo…前端

微店前端工程化起步於一個內部產品 vbuilder,對外咱們有一個開源版本 bio-clivue

去年咱們也寫過一篇文章介紹該產品: bio: 一站式前端開發工具react

這麼長時間過去了,咱們在前端工程化方面有了哪些變化、遇到了哪些問題、用怎樣的方案解決這些問題等等,值得爲你們再分享。webpack

V0.0

這裏也就是介紹下背景,爲何咱們會開發 vbuilder。git

整體思路就是:將重複性工做集成化。es6

當時,團隊面臨幾個問題:github

  • 重複:每一個項目要新開一個腳手架(webpack / gulp 之類)
  • 混雜:工程目錄既包含腳手架文件,也包含業務文件
  • 混雜packge.json 中的依賴既有腳手架的依賴,也有業務依賴,難以區分
  • 難更新:腳手架一旦肯定,幾乎再也不更新,如 webpack 1.0 的項目極有可能會一直維持在 webpack 1.0 狀態
  • 協做:團隊協做中,項目的技術棧紛雜,不一樣人員維護同一個項目成本高昂,如:需從新理解對應工程配置等

總結爲下圖:web

image

基於以上問題,咱們開始了 vbuilder 的研發。chrome

最終產品以命令行的形式發佈。json

此時的 vbuilder 爲 V0.0 狀態。

V1.0

vbuilder V1.0 提供瞭如下能力:

  • 默認命令集:內置一套命令集,用於常見功能開發,包括 mock / update / help
  • 靜默更新:用戶安裝一次命令即無需關注更新,其更新自行靜默完成
  • 收斂腳手架:將工程內的腳手架配置隱藏,並統一管理,開發者可快速聚焦業務邏輯
  • 開放接入腳手架:不限制技術棧類型(vue / react / angular / weex 等),開放接入不一樣技術棧
  • 插件化:除內置命令集外,插件化擴展命令集,供團隊同窗實現訂製邏輯

vbuilder 的不斷推動下,咱們欣喜地看到,團隊發生了一些變化:

  • 便捷:新項目一個命令即建立,直接開始業務開發
  • 純粹:工程目錄只保留了業務文件,腳手架等工程配置被隱藏
  • 更新:腳手架被收斂爲統一管理,統一更新,儘量應用最新的技術棧
  • 協做:絕大部分項目協做的成本範圍收斂到 「業務邏輯」,剔除了 「工程配置邏輯」,協做成本大大下降
  • 開放:在收斂腳手架配置的同時,開放性接入各種技術棧腳手架,如 weex / vms / 後臺管理 / serverside project
  • 協做:團隊統一性的技術更新得以快速進行,不會再遇到因工程配置不一樣不斷適配的問題

總結爲下圖:

image

V1.0 出現後,推動的很順利,在推動過程當中秉持以下原則:

  • 提效:幫助業務開發者節省時間
  • 共擔:開發者參與生態建設(腳手架開發維護、插件開發),至少在績效上會得以加分
  • 好用:使用方式簡單好用,才讓人有用的慾望

V1.0 基本解決了如下角色的痛點:

  • 後端同窗:內部系統開發場景被 100% 覆蓋
  • 前端同窗:絕大部分業務場景被覆蓋
  • 腳手架開發者:強大的腳手架被開發好後,得以快速推廣
  • 插件開發者:自定義命令,知足個性化開發

V1.0 的問題

  • 封閉性

    高度定製化的工程配置需求實現難度增大

    腳手架配置的主題被隱藏,雖然仍然開放給開發者一些配置性文件,對於高度定製化的配置需求而言依然杯水車薪。

    此時,就必須新開一個腳手架,從新接入 vbuilder 體系。

    在 「開放性」 來講,打了折扣。

  • 插件開發的衝突

    因爲 vbuilder 是基於命令行開發,插件開發者擴展自定義命令式,依然是自定義命令行,團隊規模不斷擴大的狀態下,很容易出現不一樣插件使用同一個命令,被同時安裝的狀態下,重複執行該命令。

V2.0

V2.0 至少要解決 V1.0 存在的問題,同時須要有更明確的發展方向。

不過,V2.0 依然基於命令行。

V2.0 如何解決封閉性問題

V1.0 的思路是 「閉合」,雖然有必定的開放性,但仍然不夠。

V2.0 新增 「開放」 的能力,腳手架配置能夠被隱藏,也能夠隨時在須要的時候暴露在工程配置中,進行定製化開發。

固然,會遇到腳手架難以統一管理的問題,這一點仍然有辦法能夠解決。

由於被暴露的工程配置是 vbuilder 提供的,vbuilder 得以方便地統計哪些項目使用了自定義的腳手架,將通用型工具包下發給該工程。

V2.0 如何解決插件開發的衝突

  • 問題 1:插件間的衝突

    舉個例子,有兩個插件中,都有一個命令 run。若是用戶安裝了這兩個插件,在執行 run 命令的時候,兩個插件的邏輯均會觸發。

    在某些狀況下,這不是用戶但願看到的場景,可能 TA 但願的只是運行插件 A 的命令 run

  • 問題 2:插件命令集與內置命令的衝突

    例如,內置命令集中有命令 init,而某個插件也有 init

    那麼在用戶執行 init 命令時,依然會執行兩遍邏輯。

  • 怎樣解決?

    咱們組合使用瞭如下方案:

    • vbuilder 檢測是否有重複命令,若有,提示用戶是都運行、仍是選擇運行某一個插件中的命令

    • 爲命令圈定生效條件

      vbuilder 的命令行基於 commander。咱們基於 commander 擴展了一些方法。

      假如咱們但願,插件中的命令 show 只在工程目錄中 xx.show 文件存在的狀況下生效,那麼代碼以下:

      commander
      .command('show [param]')
      .effect(cwd => fs.existsSync(path.join(cwd, 'xx.show'))) ---- 這是咱們擴展的命令
      .description('個人自定義命令')
      .action((param, options) => {
      	console.log('my show');
      });
      複製代碼
    • 爲內置命令集聲明其爲「內置命令」,插件命令能夠阻止內置命令執行

      假如插件中有個命令 init,而 vbuilder 內置命令中也有 init,咱們但願插件中的 init 命令生效,內置命令不生效,該怎麼作呢?

      咱們擴展了 commander 的 2 個方法:declareDefault 聲明內置命令、preventDefault 阻止內置命令執行。

      定義內置命令時,代碼以下:

      commander
      .command('init [param]')
      .declareDefault() --- 聲明內置命令
      .description('內置的 init 命令')
      .action((param, options) => {
      	console.log('init inside');
      });
      複製代碼

      開發插件命令時,代碼以下:

      commander
      .command('init [param]')
      .preventDefault() --- 阻止內置命令執行
      .description('內置的 init 命令')
      .action((param, options) => {
      	console.log('init inside');
      });
      複製代碼

      Commander 的源碼只有 1000 行左右,邏輯仍是很清晰的,擴展起來很是方便,這裏再也不列舉實現。

V2.0 的新功能

在命令行這個場景下,咱們把 vbuilder 定義爲公司內部開發的一個「水電煤」性質的基礎設施。

經過 vbuilder,咱們新增瞭如下場景:

  • 支持 chrome 插件 es6/7 化開發
  • 支持組件庫快速開發
  • 支持 js 工具庫快速開發
  • 支持快速打開文檔庫等等

得益於插件化,經過充分調動開發者積極性,咱們能夠將其能力無限延展。

V3.0

咱們目前尚未進入 3.0 的開發,但有一些方向是咱們能夠嘗試的:

  • cloudIDE(內部已有該類平臺)
  • vscode 定製化 IDE,該類場景在超大型團隊比較適合,IDE 定製化開發有更多的應用場景,更快的開發效率
  • 雲化(其實不算新了,不少公司已經實現了雲化)

這是目前咱們在微店前端工程化領域的一些實踐和思考,但願對你們有幫助。

相關文章
相關標籤/搜索