低代碼平臺(tái)邊界探索:多技術(shù)棧支持及高低代碼混合開發(fā)(低代碼平臺(tái)技術(shù)框架)
本文整理自華為云主任工程師莫春輝在 GMTC 全球大前端技術(shù)大會(huì)(深圳站)2021 的演講《多技術(shù)棧及高低代碼混合開發(fā)——華為云低代碼平臺(tái)架構(gòu)探討》。
當(dāng)前,華為云部門內(nèi)部的前端技術(shù)棧并不統(tǒng)一,比如華為云官網(wǎng)的 Console 控制臺(tái)使用 Angular 技術(shù)棧開發(fā),其他內(nèi)部 IT 系統(tǒng)使 Vue 技術(shù)棧開發(fā)。因此,華為云要建設(shè)一套低代碼搭建平臺(tái),對(duì)內(nèi)提效能要同時(shí)兼顧 Angular 和 Vue 兩種技術(shù)棧,對(duì)外建生態(tài)則要同時(shí)支持 Vue 和 React 技術(shù)棧。
另外,目前業(yè)界的低代碼搭建平臺(tái)大多局限于簡(jiǎn)單的應(yīng)用開發(fā),而華為云自身的業(yè)務(wù)邏輯中,既有需要用高代碼開發(fā)的復(fù)雜頁面,又存在一些簡(jiǎn)單頁面。這些復(fù)雜頁面,你很難完全通過可視化拖拽搭建出來,但對(duì)于簡(jiǎn)單的頁面,又希望能夠使用可視化拖拽快速生成。因此,支持高低代碼混合開發(fā)的需求就擺在了我們的眼前。
1. 華為云低代碼平臺(tái)建設(shè)背景與訴求
華為云低代碼平臺(tái)的建設(shè)背景
在 Gartner 的定義中,低代碼平臺(tái)被稱為企業(yè)級(jí)低代碼應(yīng)用平臺(tái),是支持快速應(yīng)用開發(fā),使用陳述性、高級(jí)的編程抽象(如基于模型驅(qū)動(dòng)和元數(shù)據(jù)編程語言)實(shí)現(xiàn)一站式應(yīng)用部署、執(zhí)行和管理的應(yīng)用平臺(tái)。不同于傳統(tǒng)的應(yīng)用平臺(tái),它支持用戶界面、業(yè)務(wù)邏輯和數(shù)據(jù)服務(wù)的開發(fā),并以犧牲跨平臺(tái)的可移植性、應(yīng)用開放性為代價(jià)來提高生產(chǎn)效率。
正因?yàn)闋奚丝缙脚_(tái)的可移植性和應(yīng)用的開放性,各廠商開發(fā)的低代碼平臺(tái),都不約而同地朝著“低”的方向走,越低越好,甚至是無代碼、智能生成代碼,于是就容易忽略“高”的需求,忽略與“高”的結(jié)合。而且,各廠商都希望用戶從頭到尾都在自己的平臺(tái)上進(jìn)行開發(fā)、全程托管,于是就容易忽略“被托”的需求,或者說“被集成”的需求,忽略與存量應(yīng)用的結(jié)合。
這種忽略其實(shí)也是不得已而為之。如果不犧牲跨平臺(tái)可移植性,就有可能支撐不同平臺(tái)不同技術(shù)棧、生成可移植的代碼,與現(xiàn)有的高代碼(純手寫代碼)相結(jié)合;如果不犧牲應(yīng)用開放性,就有可能更好地支撐被集成的需求,靈活地與存量應(yīng)用相結(jié)合。事實(shí)上,企業(yè)內(nèi)部有非常多的存量應(yīng)用,這些存量應(yīng)用也想通過低代碼平臺(tái)去提升開發(fā)效率。
目前華為內(nèi)部已經(jīng)有幾套低代碼平臺(tái),華為云的低代碼平臺(tái)是否存在重復(fù)造輪子的嫌疑?2021 年 7 月北京的 GMTC 大會(huì)上,阿里巴巴研究員玉伯在談前端現(xiàn)狀的時(shí)候說到:阿里內(nèi)部的低代碼平臺(tái)也很多,但深入到業(yè)務(wù)層面去看,你就會(huì)發(fā)現(xiàn),那些“輪子”都是合理的,它確實(shí)是在解決特定領(lǐng)域的特定問題。華為云低代碼平臺(tái)的建設(shè)初衷,就是用來解決華為云領(lǐng)域內(nèi)部的存量應(yīng)用想通過低代碼平臺(tái)提升開發(fā)效率的問題。
如何在盡量不犧牲跨平臺(tái)可移植性、盡量不犧牲應(yīng)用開放性的情況下建設(shè)華為云低代碼平臺(tái)?這就是本文要探討的問題。以下內(nèi)容,我們將華為云領(lǐng)域存量應(yīng)用的業(yè)務(wù)需求為線索,分析這些業(yè)務(wù)需求背后的實(shí)質(zhì)問題,討論用什么樣的技術(shù)方案去應(yīng)對(duì)這些問題,以及用什么樣的平臺(tái)架構(gòu)去承載技術(shù)方案,最后講講建設(shè)過程中我們所踩過的坑。
華為云 CRM 系統(tǒng)的低代碼需求分析
華為云內(nèi)部有一個(gè) CRM 客戶關(guān)系管理系統(tǒng),這個(gè)系統(tǒng)已經(jīng)開發(fā)完成并且上線運(yùn)行,屬于存量應(yīng)用。由于后面不斷有新的需求,需要開發(fā)新的頁面,而那些新的頁面又跟原來的頁面非常相似,所以重復(fù)性的開發(fā)工作比較多,于是 CRM 的開發(fā)人員就想利用低代碼平臺(tái)來搭建新頁面。
由于新的頁面跟原來的頁面非常相似,CRM 的需求其實(shí)是想將原來的頁面封裝成可配置的頁面模板。這樣在面對(duì)新需求時(shí),只需在低代碼平臺(tái)里配置一下頁面模板就能產(chǎn)生新的頁面,不用再重復(fù)開發(fā)??膳渲玫捻撁婺0逡彩怯?CRM 開發(fā)人員在低代碼平臺(tái)搭建而成,而產(chǎn)生的新頁面則必須提供源代碼,以便與 CRM 原系統(tǒng)一起編譯構(gòu)建,組成一個(gè)完整的應(yīng)用,如下圖所示:
左圖是開發(fā)人員日常使用的 IDE(Visual Studio Code),低代碼平臺(tái)作為 IDE 的插件嵌入到 IDE 里。開發(fā)人員在平臺(tái)里通過可視化方式搭建頁面,保存頁面的時(shí)候平臺(tái)會(huì)生成頁面的源代碼(中圖),與原來純手寫的代碼一起編譯生成應(yīng)用(右圖)。這里的可視化搭建相當(dāng)于部分代替了原本需要手寫代碼的工作。
CRM 低代碼需求背后的實(shí)質(zhì)問題,其實(shí)是 ProCode 與 LowCode 的混合開發(fā)。ProCode 就是我們傳統(tǒng)意義上的高代碼開發(fā),即所有代碼都是純手寫的,而 LowCode 就是借助可視化工具搭建頁面,只需編寫少量代碼。所謂的高低代碼混合開發(fā)就是:在本地 IDE 里,有些場(chǎng)景直接手寫代碼,有些場(chǎng)景則用可視化工具搭建,生成代碼到本地工程?;旌祥_發(fā)的目的,仍然是想充分利用低代碼平臺(tái)的能力,提高開發(fā)階段的生產(chǎn)效率。
華為云 DevOps 系統(tǒng)的低代碼需求分析
再來看一下華為云另一個(gè)領(lǐng)域的低代碼需求,這個(gè)需求來自 DevOps 系統(tǒng)。在 DevOps 流水線上,我們?cè)试S用戶添加自定義的插件,這個(gè)插件能讓用戶干預(yù)構(gòu)建和部署過程。
在使用插件前,需要通過一些頁面來配置插件的參數(shù),而這些頁面當(dāng)前是由 DevOps 團(tuán)隊(duì)開發(fā)。為了減輕團(tuán)隊(duì)的負(fù)擔(dān),他們希望借助低代碼平臺(tái)的能力,讓用戶在 DevOps 網(wǎng)站上直接搭建頁面,頁面保存后同樣生成源代碼,集成到 DevOps 系統(tǒng)里。這個(gè)需求與 CRM 不同之處有三點(diǎn):
- 目標(biāo)用戶不同
- CRM 是 CRM 系統(tǒng)的開發(fā)人員使用低代碼平臺(tái)搭建系統(tǒng)頁面,DevOps 則是 DevOps 系統(tǒng)的用戶使用低代碼平臺(tái)搭建插件配置頁面。
- 嵌入方式不同
- CRM 是在 IDE 里嵌入低代碼平臺(tái),屬于線下開發(fā)。DevOps 則是在 DevOps 網(wǎng)站上嵌入低代碼平臺(tái),屬于線上開發(fā)。
- 技術(shù)棧不同
- CRM 采用 Angular 技術(shù)棧,DevOps 采用 Vue 技術(shù)棧。所以在 CRM 低代碼平臺(tái)搭建頁面所用的組件,必須是 CRM 系統(tǒng)當(dāng)前使用的 Angular 組件,而 DevOps 則是 Vue 組件。CRM 低代碼平臺(tái)生成的源代碼,必須是 Angular 技術(shù)棧,而 DevOps 則是 Vue 技術(shù)棧。如下圖所示:
如果僅僅是生成不同技術(shù)棧的源碼,相信很多低代碼平臺(tái)都能做到,但是我們面對(duì)的是不同技術(shù)棧的組件。比如一個(gè)按鈕,CRM 是用 Angular 開發(fā)的,DevOps 是用 Vue 開發(fā)的。兩個(gè)技術(shù)棧開發(fā)的按鈕,它們的屬性、方法、事件,甚至功能都不一定相同。打個(gè)比方,我們要給這個(gè)按鈕設(shè)置顏色,Angular 的屬性名稱叫 type,屬性的值是 success,而 Vue 的屬性名稱叫 color,屬性的值是 green,兩者并不匹配,如下圖所示:
所以,用 Angular 組件搭建的頁面,生成的 Vue 源碼是跑不通的。有些人可能會(huì)說,通過 DSL 做屬性映射,但是,如果功能不同,用 DSL 也無濟(jì)于事。那么,我們是不是我們要為不同技術(shù)棧,不同領(lǐng)域打造不同的低代碼平臺(tái)呢?
如果這樣做了,我們的成本會(huì)非常高,這個(gè)成本不僅包括軟硬件資源的投入,還包括研發(fā)和運(yùn)維的投入。而且各技術(shù)棧的低代碼物料的不通用,還會(huì)造成物料生態(tài)的割裂。因此我們的低代碼平臺(tái)方案要能夠支持不同的技術(shù)棧。
與傳統(tǒng) Visual Studio 可視化 IDE 的區(qū)別
把低代碼平臺(tái)嵌入到 IDE 里,通過可視化搭建生成源代碼,這與 20 年前流行的 Delphi/ C Builder/ J Builder/ Visual Studio 非常類似,當(dāng)然這些工具今天也還有人在用。
如下圖所示的 Visual Studio,左邊是可以拖拽的組件,中間上方是畫布,左邊的組件可以拖到畫布里,中間下方是代碼編輯區(qū)域,右邊是文件系統(tǒng)以及組件的屬性配置面板??梢?,雖然技術(shù)在向前演進(jìn),但是解決問題的思路又回到了原點(diǎn)。
兩者的相同點(diǎn)不難看出,都是可視化搭建,都會(huì)生成源代碼。要厘清兩者的區(qū)別,我們從以下三個(gè)維度去探討:
- 適用人群
- 低代碼平臺(tái)面向的人群,通常是不太懂編程的業(yè)務(wù)人員,或者能在幫助文檔下寫一點(diǎn)簡(jiǎn)單的業(yè)務(wù)邏輯代碼,可視化搭建是他們的主要工作,寫少量的代碼只是輔助工作。在高低代碼混合開發(fā)的方案里,適用人群可分為兩類,一類是不太懂編程的業(yè)務(wù)人員,主要負(fù)責(zé)業(yè)務(wù)頁面的搭建,另一類是傳統(tǒng)的專業(yè)編程人員,主要負(fù)責(zé)業(yè)務(wù)邏輯的編寫,兩者協(xié)同開發(fā)一個(gè)應(yīng)用。Visual Studio 面向的是單一人群,即專業(yè)編程的開發(fā)人員,可視化拖拽組件只起到輔助作用,大部分時(shí)間他們都在編寫和調(diào)試代碼,獨(dú)立完成一個(gè)應(yīng)用的開發(fā)。
- 開發(fā)語言
- 低代碼平臺(tái)本身與開發(fā)語言無關(guān),即便在平臺(tái)上寫的少量代碼,也是前端通用的 JavaScript 語言。在高低代碼混合開發(fā)的方案里,不太懂編程的業(yè)務(wù)人員可能需要掌握 JavaScript 語言,用來編寫小部分的業(yè)務(wù)邏輯。另外,由于本文的低代碼方案可以生成不同技術(shù)棧的源代碼,所以專業(yè)編程人員需要掌握 Angular 或 Vue 等前端開發(fā)框架,才能調(diào)用低代碼平臺(tái)生成的源碼。Visual Studio 的可視化工具與 IDE 本身是天然集成的,一個(gè)子產(chǎn)品只支持一種開發(fā)語言,比如 Visual Basic 等。由于主流的前端框架并無統(tǒng)一的組件庫,Visual Studio 系列也就沒有諸如 Visual Angular 或 Visual Vue 的子產(chǎn)品,市面上也沒有類似成熟的面向前端框架開發(fā)的可視化 IDE,所以低代碼平臺(tái)的可視化搭建工具正好彌補(bǔ)這一空缺。
- 協(xié)同開發(fā)
- 這是高低代碼混合開發(fā)的方案特有的,Visual Studio 并不存在這種情況。因?yàn)榈痛a平臺(tái)雖然嵌入到 IDE 里,但仍然是獨(dú)立于 IDE 的模塊,其生成的源代碼需要跟本地純手寫的代碼協(xié)同工作,才能達(dá)成混合開發(fā)的目標(biāo)。協(xié)同的方式按模塊顆粒度分為兩種:一種是頁面級(jí)別,另一種是組件級(jí)別。頁面級(jí)別是指平臺(tái)生成的源代碼本身是一個(gè)頁面,本地工程通過路由直接跳轉(zhuǎn)到該頁面即可。這種級(jí)別與高代碼部分耦合度最小,也最容易集成。組件級(jí)別是指平臺(tái)生成的源代碼只是頁面的一個(gè)組成部分,需要跟頁面的其他純手寫的部分相互通訊、協(xié)調(diào)運(yùn)行。這種級(jí)別與高代碼部分耦合度非常大,但卻是混合開發(fā)的普遍場(chǎng)景,為此我們引入橋接源來解決協(xié)同開發(fā)的問題。
讓業(yè)務(wù)人員參與低代碼平臺(tái)開發(fā)
厘清兩者的區(qū)別之后,有人可能會(huì)指出:為什么讓業(yè)務(wù)人員參與混合開發(fā),全部由專業(yè)編程人員不行嗎?為什么要高低代碼混合開發(fā)?把開發(fā)流程復(fù)雜化,增加學(xué)習(xí)成本。有些人甚至還指出:LowCode 是行業(yè)毒瘤,它沒有任何未來,不值得我們?nèi)魏蔚耐顿Y和想法。讓不懂軟件開發(fā)的人可以寫代碼,這個(gè)想法就是錯(cuò)的,而且錯(cuò)的非常離譜。我們從以下兩個(gè)方面來回應(yīng)這些問題和說法:
- 數(shù)字化轉(zhuǎn)型需要業(yè)務(wù)人員參與
- 在企業(yè)數(shù)字化轉(zhuǎn)型的大背景下,應(yīng)用軟件呈爆炸式增長(zhǎng),開發(fā)應(yīng)用所需的專業(yè)人員或者供不應(yīng)求或者成本太高。于是降低開發(fā)門檻,讓懂業(yè)務(wù)的人員直接參與應(yīng)用構(gòu)建,就成了低代碼平臺(tái)的發(fā)展機(jī)遇。對(duì)于企業(yè)的存量應(yīng)用,仍然需要面對(duì)快速變化的業(yè)務(wù)需求,但這些應(yīng)用很難直接拋棄另起爐灶,改用低代碼平臺(tái)重新構(gòu)建。在專業(yè)編程人力不足的情況下,或者站在提高研發(fā)效率、降低維護(hù)成本的角度上考慮,都希望讓了解業(yè)務(wù)需求的業(yè)務(wù)人員能直接參與進(jìn)來,與專業(yè)編程人員一起更新這些存量的應(yīng)用。
- 低代碼平臺(tái)本質(zhì)上仍然是軟件開發(fā)工具
- 低代碼是一種軟件開發(fā)技術(shù),屬于軟件開發(fā)的高級(jí)語言。低代碼開發(fā)平臺(tái)通常整合了軟件開發(fā)所需的 IDE,有些還覆蓋軟件開發(fā)的全生命周期,提供數(shù)據(jù)建模與流程編排的能力,提供編程接口與系統(tǒng)集成的能力等。因此,低代碼與其他軟件開發(fā)技術(shù)一樣,值得我們投資和發(fā)展。低代碼開發(fā)平臺(tái)有自己專屬的開發(fā)語言,本身也能夠獨(dú)立完成應(yīng)用開發(fā),當(dāng)要與傳統(tǒng)的純代碼開發(fā)方式融合時(shí),必然存在兩種開發(fā)語言的磨合。這種磨合是有成本的,但成本是可控的,特別是低代碼平臺(tái)直接生成源代碼,能極大方便本地調(diào)試與快速排查問題。
本文我們所討論的華為云低代碼平臺(tái),不同于市面上常見的低代碼平臺(tái),它不僅僅可以實(shí)現(xiàn)簡(jiǎn)單的增刪改查頁面,還能支持復(fù)雜的 CRM 系統(tǒng)頁面開發(fā),還能生成 CRM 和 DevOps 不同技術(shù)棧的源代碼,并與原 CRM 和 DevOps 系統(tǒng)編譯集成。此外,它讓不懂編程的業(yè)務(wù)人員,與專業(yè)的開發(fā)人員一起協(xié)同工作,每個(gè)人負(fù)責(zé)各自擅長(zhǎng)的部分,使得低代碼平臺(tái)能夠適應(yīng)更多的業(yè)務(wù)場(chǎng)景,覆蓋更多的行業(yè)領(lǐng)域,進(jìn)一步拓展了低代碼開發(fā)平臺(tái)的邊界。
2. 支持多技術(shù)棧與高低代碼混合開發(fā)
前面描述的 CRM 和 DevOps 系統(tǒng)的低代碼需求,除了高低代碼混合與支持多技術(shù)棧外,還有搭建復(fù)雜頁面的場(chǎng)景。企業(yè)級(jí)的 CRM 客戶關(guān)系管理系統(tǒng),如果不能像 Salesforce 一樣,把客戶關(guān)系管理系統(tǒng)都做透,通過配置化實(shí)現(xiàn)客戶側(cè)的定制,那么低代碼平臺(tái)很難通過可視化搭建,構(gòu)建復(fù)雜的 CRM 系統(tǒng)頁面。這也是大多數(shù)低代碼平臺(tái)為什么只專注于簡(jiǎn)單的增刪改查頁面、或者流程審批電子流的原因。
然而這些問題如果沒有解決,那代碼混合開發(fā)就無從談起。企業(yè)內(nèi)部的存量應(yīng)用,不會(huì)因?yàn)槟阕霾坏骄秃?jiǎn)化頁面,畢竟業(yè)務(wù)邏輯的復(fù)雜度本身就無法忽視。
如何可視化搭建復(fù)雜的 CRM 系統(tǒng)頁面
這個(gè)問題我們給出的解決方案是:為用戶提供自助搭建可復(fù)用區(qū)塊的能力。
什么是區(qū)塊?我們來看下面這張圖,一個(gè)頁面通常由多個(gè)區(qū)塊拼接而成,每個(gè)區(qū)塊由一到多個(gè)業(yè)務(wù)組件構(gòu)成,每個(gè)業(yè)務(wù)組件都由基礎(chǔ)組件實(shí)現(xiàn)。在低代碼平臺(tái)里,基礎(chǔ)組件和業(yè)務(wù)組件都屬于原子組件,即不可拆分的、平臺(tái)內(nèi)置的、可以拖到畫布用于搭建區(qū)塊的組件。一個(gè)復(fù)雜的頁面通??梢圆鸱殖扇舾蓚€(gè)區(qū)塊,而區(qū)塊里面也可以嵌套區(qū)塊。只要讓用戶能夠復(fù)用已搭建好的區(qū)塊,復(fù)雜的頁面就像搭積木一樣,一層層摞起來即可。
我們用低代碼平臺(tái)搭建的頁面,會(huì)有一個(gè)描述頁面信息的文件,這個(gè)文件我們稱為頁面 Schema。如下圖左邊所示,可以看到這個(gè)頁面只包含兩個(gè)組件,一個(gè)是 Button,另一個(gè)是 Input。如果我們認(rèn)為這個(gè)頁面可以復(fù)用,我們就把它轉(zhuǎn)為區(qū)塊,這時(shí)候該區(qū)塊可以理解為:可配置的頁面。所以只需在頁面的 Schema 里面,增加區(qū)塊可配置的屬性,它就變成了描述區(qū)塊的 Schema。如下圖右邊所示,該區(qū)塊暴露了兩個(gè)配置項(xiàng):buttonSize 和 inputSize,分別對(duì)應(yīng)頁面包含的 Button 組件和 Input 組件的屬性。
以下這張圖展示了低代碼區(qū)塊的創(chuàng)建和消費(fèi)過程。首先,從新建空白畫布開始,用戶在畫布上拖拽組件、搭建區(qū)塊,接著添加區(qū)塊的業(yè)務(wù)邏輯。這里需要說明的是,我們提供了一些橋接方法,讓用戶可以調(diào)用高代碼的部分功能,即前面提到的高低代碼混合開發(fā)時(shí),需要跟頁面的其他純手寫的部分相互通訊、協(xié)調(diào)運(yùn)行。第四步就是保存區(qū)塊,讓用戶選擇暴露的配置項(xiàng),即將區(qū)塊里所有組件的所有屬性都羅列出來,讓用戶選擇哪些屬性可以對(duì)外暴露,以便復(fù)用的時(shí)候進(jìn)行配置。第五步是發(fā)布區(qū)塊到物料中心,這樣下次新建頁面的時(shí)候,用戶就可以將這個(gè)區(qū)塊拖到畫布上,重復(fù)使用。
另外,由于我們的頁面和區(qū)塊都會(huì)生成源代碼。如果兩個(gè)頁面都用到同一個(gè)區(qū)塊,只是區(qū)塊的配置有所不同,那么在生成這兩個(gè)頁面源碼的同時(shí),我們只會(huì)生成一份區(qū)塊源碼,然后讓這兩個(gè)頁面都引用這個(gè)相同的區(qū)塊。
如何在畫布里展現(xiàn)不同技術(shù)棧的 UI 組件
目前大多數(shù)的低代碼平臺(tái)為了方便實(shí)現(xiàn),都會(huì)限定畫布只支持一種技術(shù)棧,甚至一套組件庫。因?yàn)闆]有為用戶提供頁面源代碼的需求,搭建出來的頁面也不需要被其他系統(tǒng)集成,所以沒必要考慮多技術(shù)棧,用一套組件庫實(shí)現(xiàn)的成本是最低的。但是在華為云領(lǐng)域,面對(duì) CRM 和 DevOps 的需求,我們要解決一個(gè)問題:如何在畫布里展現(xiàn)不同技術(shù)棧的 UI 組件?這個(gè)問題我們給出的解決方案是——使用 Web Component 技術(shù)。
上圖是 InfoQ 2020 年一季度,Web 開發(fā)相關(guān)的語言、標(biāo)準(zhǔn)、模式趨勢(shì)圖??梢钥吹?Web Component 處于中間位置,說明它已經(jīng)到了主流成熟階段,我們可以使用 Web Component 來解決跨技術(shù)棧問題。
目前三大主流前端框架:Angular、React、Vue 都已經(jīng)提供官方的 Web Component 轉(zhuǎn)換工具,我們利用這些轉(zhuǎn)換工具,就可以輕松的將各技術(shù)棧的 UI 組件,全部包裹成 Web Component,然后當(dāng)做 HTML 原生組件顯示到畫布上。需要指出的是,在生成的代碼里,我們引用的仍然是原始的 UI 組件,而不是 Web Component,這是因?yàn)楫嫴际窃O(shè)計(jì)態(tài),源碼是運(yùn)行態(tài),兩者是不同的。
當(dāng)前 Angular、React、Vue 是三大主流前端框架,未來又會(huì)出現(xiàn)什么樣的框架代替它們呢?我們不得而知。但是,不管未來的前端框架如何變化,我們都先用 Web Component 技術(shù)收斂,再通過 DSL(Domain Specific Language)機(jī)制發(fā)散,生成不同框架不同技術(shù)棧的源碼,這就是我們低代碼平臺(tái)的演進(jìn)策略:
我們來舉個(gè) Vue 的例子說明 Web Component 方案。首先按照 Vue 官方的示例,定義一個(gè) Vue 的組件,并注冊(cè)成為 Web Component。然后在畫布的 HTML 代碼里,我們聲明該 Web Component。假設(shè)這個(gè) Vue 組件暴露的 options 屬性,是數(shù)組類型。我們知道,在 HTML 標(biāo)簽上,attribute 屬性只能設(shè)置為字符串或數(shù)值類型,因此,我們需要通過 JavaScript 腳本動(dòng)態(tài)設(shè)置 options 的屬性值。如下圖所示:
接下來,我們將畫布的 HTML 內(nèi)容,用 AST 抽象語法樹,解析成一個(gè) JSON 對(duì)象,即描述頁面的 Schema。從下面左側(cè)的圖可以看到,Web Component 組件的 options 屬性,它仍然是數(shù)組類型。然后我們通過 DSL 將頁面描述 Schema 轉(zhuǎn)換成 Vue 的源碼。從下面右側(cè)的圖可以看到,Vue 組件的 options 屬性,也仍舊是數(shù)組類型。于是我們發(fā)現(xiàn),從 Web Component 封裝組件開始,到生成 Vue 的源碼,整個(gè)過程中,給組件屬性設(shè)置的值是可以透?jìng)鞯摹?/p>
講到這里,大家可能會(huì)有疑問,為什么不能在 Vue 應(yīng)用中,直接使用 Web Component?以下列出 5 個(gè)理由,都摘自 Vue 的官網(wǎng)。簡(jiǎn)而言之,就是 Web Component 技術(shù)還不夠強(qiáng)大,還不能完全替代現(xiàn)有的主流前端框架。
- 我們需要一個(gè)聲明式的、高效的模板系統(tǒng)
- 我們需要一個(gè)有助于跨組件邏輯提取和重用的響應(yīng)式狀態(tài)管理系統(tǒng)
- 我們需要一個(gè)能在服務(wù)器端渲染組件并在客戶端集成的高效方法
- 原生插槽沒有 Vue 的作用域插槽提供的組件整合機(jī)制
- 隱式 DOM scoped CSS 的自定義元素需要將 CSS 嵌入到 JS 中
生成源代碼 VS 運(yùn)行時(shí)渲染
要將畫布的描述生成不同技術(shù)棧的源碼,需要借助 DSL 機(jī)制。我們知道,用可視化方式搭建頁面,這個(gè)屬于設(shè)計(jì)態(tài)。將頁面描述文件通過 DSL 轉(zhuǎn)換成源代碼,然后編譯成可以運(yùn)行的應(yīng)用,這個(gè)屬于運(yùn)行態(tài)??梢赃@么說,DSL 的作用就是將低代碼從設(shè)計(jì)態(tài)轉(zhuǎn)換成運(yùn)行態(tài)。
但是,并不是所有低代碼平臺(tái)都會(huì)采用生成源碼的方案。事實(shí)上,有很多低代碼平臺(tái)采用的是運(yùn)行時(shí)渲染的方案,即將頁面描述文件直接傳給運(yùn)行時(shí)解析引擎,然后動(dòng)態(tài)地渲染頁面。兩種方案各有所長(zhǎng),這里列出四個(gè)對(duì)比項(xiàng),如下圖所示:
第一項(xiàng),從性能上來看,運(yùn)行時(shí)渲染要用到解析引擎,這個(gè)肯定不如生成源碼編譯跑的快;
第二項(xiàng),由于運(yùn)行時(shí)渲染一般要求所有應(yīng)用都用統(tǒng)一的解析引擎,因此升級(jí)和修復(fù)平臺(tái)問題時(shí),只需針對(duì)統(tǒng)一的解析引擎,其效率自然要高于每個(gè)應(yīng)用的源碼都需要重新編譯的方式;
第三項(xiàng),DSL 生成源碼天然具有很高的靈活性,只要用戶通過自定義 DSL,就能生成任意想要的源碼,因此擴(kuò)展性和開放性要比運(yùn)行時(shí)渲染高;
第四項(xiàng),開發(fā)和運(yùn)維的成本,兩者應(yīng)該相差不大。
3.低代碼平臺(tái)架構(gòu)開發(fā)及生態(tài)建設(shè)思路
低代碼平臺(tái)架構(gòu)設(shè)計(jì)
下圖是我們低代碼平臺(tái)架構(gòu)設(shè)計(jì)圖。先看底部的平臺(tái)服務(wù),我們會(huì)利用華為云原生的能力搭建后端服務(wù),會(huì)跟華為云的業(yè)務(wù)集成互通,比如跟我們的 Console 控制臺(tái)業(yè)務(wù)集成等。中間這塊是我們搭建平臺(tái)的核心,底層能力提供搭建頁面所需的基礎(chǔ)組件、移動(dòng)組件和業(yè)務(wù)組件,提供頁面運(yùn)行用到的邏輯編排、流程編排。
往上一層是我們用來粘合各個(gè)模塊的平臺(tái)協(xié)議,這個(gè)頁面搭建協(xié)議是用來描述頁面信息的,而組件描述協(xié)議是用來給組件設(shè)置屬性的,物料資產(chǎn)協(xié)議是用來描述平臺(tái)用到的組件、區(qū)塊以及技術(shù)棧等信息,DSL 轉(zhuǎn)換協(xié)議則是用來將頁面或區(qū)塊 Schema 轉(zhuǎn)換成各技術(shù)棧的源代碼。
低代碼設(shè)計(jì)器是我們核心中的核心。首先從導(dǎo)入物料開始,中間是設(shè)計(jì)器的各個(gè)模塊,這些模塊會(huì)接入我們的平臺(tái)擴(kuò)展生態(tài),包括設(shè)計(jì)器的插件生態(tài),以及組件和區(qū)塊生態(tài)。最后,設(shè)計(jì)器還要負(fù)責(zé)生成源代碼,適配多終端多技術(shù)棧。再看上圖右下角,我們?yōu)榱藢?shí)現(xiàn)設(shè)計(jì)開發(fā)一體化,會(huì)提供在線設(shè)計(jì)平臺(tái)、提供支持高低代碼混合開發(fā)的 VSCode 插件。
平臺(tái)管理中心包含很多個(gè)中心,我們會(huì)先在物料中心挑選物料,然后打成物料資產(chǎn)包,再到平臺(tái)中心選擇剛打好的物料資產(chǎn)包,用來構(gòu)建各領(lǐng)域的平臺(tái),接著在應(yīng)用中心管理各領(lǐng)域平臺(tái)生成的應(yīng)用。PaaS 平臺(tái)服務(wù)就是支撐我們?nèi)?gòu)建定制的平臺(tái),提供平臺(tái)的運(yùn)行時(shí)服務(wù),另外還要支撐應(yīng)用的設(shè)計(jì)、開發(fā)、構(gòu)建、部署等。
有了 PaaS 平臺(tái)之后,我們就可以提供 SaaS 能力,既可以開發(fā)傳統(tǒng)的中后臺(tái)應(yīng)用,也開發(fā)華為云的 Console 控制臺(tái)應(yīng)用,甚至包括我們的 WeLink 移動(dòng)端應(yīng)用、鴻蒙的多端應(yīng)用,然后再將這些應(yīng)用發(fā)布到我們的應(yīng)用生態(tài)市場(chǎng)。
低代碼平臺(tái)工作流程
下圖是我們的低代碼平臺(tái)工作流程。先從底部的低代碼后端說起,可以看到包含了前面說的物料中心、平臺(tái)中心以及應(yīng)用中心,這三個(gè)中心的后端都會(huì)連接一個(gè)數(shù)據(jù)中心,再由數(shù)據(jù)中心連接數(shù)據(jù)庫。平臺(tái)中心構(gòu)建出來的產(chǎn)物是低代碼平臺(tái)實(shí)例,VSCode 模塊根據(jù)模板工程把這個(gè)低代碼平臺(tái)實(shí)例打包編譯,構(gòu)建出一個(gè) VSCode 插件。
物料中心會(huì)構(gòu)建出兩個(gè)產(chǎn)物,分別是物料資產(chǎn)包,以及搭建頁面所需的組件庫,它們會(huì)被低代碼平臺(tái)實(shí)例動(dòng)態(tài)加載。每個(gè)平臺(tái)實(shí)例都是由設(shè)計(jì)器各個(gè)模塊組裝而成,這些設(shè)計(jì)器的模塊都來源于 npm 倉庫。每個(gè)平臺(tái)的實(shí)例都會(huì)請(qǐng)求對(duì)應(yīng)的平臺(tái)服務(wù),平臺(tái)服務(wù)提供各技術(shù)棧的頁面預(yù)覽功能,并且將生成的代碼提交到 Git 庫,再通過流水線發(fā)布應(yīng)用。
低代碼組件及區(qū)塊構(gòu)建流程
接下來我們看一下,物料中心的兩個(gè)產(chǎn)物,物料資產(chǎn)包和組件庫,它們是如何構(gòu)建的。如下圖所示,首先在物料中心的前端頁面,我們點(diǎn)擊構(gòu)建組件和區(qū)塊的按鈕,后端服務(wù)就會(huì)分別執(zhí)行構(gòu)建動(dòng)作。先看左邊的組件構(gòu)建流程,我們會(huì)根據(jù)用戶選擇的技術(shù)棧,安裝相應(yīng)的 Web Component 組件庫,接著生成構(gòu)建代碼,代碼里引入用戶選擇的組件,并且按照物料資產(chǎn)協(xié)議,輸出該組件的描述信息,最后用 Rollup 打包構(gòu)建,生成組件庫。
再來看右邊的區(qū)塊構(gòu)建流程,我們先從數(shù)據(jù)中心里獲取區(qū)塊的 Schema,然后將 Schema 轉(zhuǎn)成區(qū)塊的描述信息,所有區(qū)塊的描述信息都會(huì)插入到 material.config 文件里,這個(gè)文件是按照物料資產(chǎn)協(xié)議進(jìn)行整理,包含平臺(tái)用到的組件、區(qū)塊以及技術(shù)棧等信息,這個(gè)文件最后被打到物料資產(chǎn)包里,并且保存到數(shù)據(jù)中心。
低代碼平臺(tái)項(xiàng)目開發(fā)流程
下圖我們低代碼平臺(tái)的項(xiàng)目開發(fā)流程。流程分三個(gè)角色,首先由項(xiàng)目經(jīng)理在平臺(tái)中心新建一個(gè)項(xiàng)目,然后設(shè)置可視化設(shè)計(jì)器的默認(rèn)配置,比如設(shè)計(jì)器用什么樣的主題,是深色還是淺色主題、設(shè)計(jì)器的面板有哪些插件、工具欄上有哪些按鈕等。接著設(shè)置平臺(tái)的默認(rèn)配置,比如使用自定義的 DSL 配置、設(shè)置代碼倉庫的地址、監(jiān)控應(yīng)用所需的埋點(diǎn)信息等,下一步是設(shè)置項(xiàng)目所用的物料,比如用什么技術(shù)棧的組件、用什么領(lǐng)域的區(qū)塊及模板。最后,項(xiàng)目經(jīng)理點(diǎn)擊構(gòu)建平臺(tái)的按鈕,等平臺(tái)生成后,就會(huì)通知開發(fā)人員登錄平臺(tái)網(wǎng)址,或者安裝 VSCode 插件。
開發(fā)人員可以在平臺(tái)上創(chuàng)建低碼或無碼應(yīng)用。如果是低碼應(yīng)用,則可以創(chuàng)建分支,支持多人協(xié)作;如果是無碼應(yīng)用,只需選擇模板,做一些簡(jiǎn)單的配置。經(jīng)過一系列的迭代開發(fā),用可視化工具搭建完頁面,平臺(tái)就可以通過 DSL 生成代碼,最后用流水線部署應(yīng)用。在開發(fā)過程中,如果發(fā)現(xiàn)組件缺失,還可以通過專業(yè)前端開發(fā)相應(yīng)的組件,然后作為源碼物料導(dǎo)入到物料中心。另外,由于用戶也可以自行搭建可復(fù)用的區(qū)塊,將區(qū)塊作為低代碼物料發(fā)布到物料中心,形成物料的雙向流通。
4. 低代碼平臺(tái)建設(shè)過程中踩過的坑
第一個(gè)坑是關(guān)于 Vue 的 Web Component 轉(zhuǎn)換工具,我們使用 Vue3.2 版本推出的轉(zhuǎn)換工具。當(dāng)時(shí)發(fā)現(xiàn)一個(gè)問題,就是 Vue 組件轉(zhuǎn)換成 Web Component 之后,使用 JavaScript 腳本設(shè)置它的 property 屬性,只有第一次設(shè)置是生效的,后面再設(shè)置是無效的,請(qǐng)注意:這不是 HTML 標(biāo)簽上的 attribute 屬性。什么原因呢?
我分析了一下 Vue 的源代碼,原來轉(zhuǎn)換后的 Web Component 只在初始化時(shí)讀取 property 屬性,后面并沒有監(jiān)聽 property 屬性的變化。但是低代碼平臺(tái)就是要對(duì)畫布上的組件進(jìn)行屬性設(shè)置。
于是我就對(duì)轉(zhuǎn)換工具做了點(diǎn)改進(jìn),給轉(zhuǎn)換后的 Web Component 添加了一個(gè)方法,把要設(shè)置的屬性傳進(jìn)去,然后調(diào)用它內(nèi)部的 render 方法重新渲染組件,這樣設(shè)置就生效了。值得一提的是,我發(fā)現(xiàn) Angular 的 Web Component 轉(zhuǎn)換工具并沒有這個(gè)問題。
第二個(gè)坑是關(guān)于 VSCode 插件,我們是通過 VSCode 插件來實(shí)現(xiàn)高低代碼混合開發(fā)的需求,如下圖所示。
首先把低代碼平臺(tái)解耦,然后通過 VSCode 的 WebView 嵌入這個(gè)低代碼平臺(tái)。接著我們就發(fā)現(xiàn),平臺(tái)通過 WebView 發(fā)送網(wǎng)絡(luò)請(qǐng)求的時(shí)候,是不能攜帶 Cookie 的,這樣就導(dǎo)致我們的低代碼平臺(tái)無法進(jìn)行鑒權(quán)。
我從 VSCode 的 Github 上搜到這個(gè)問題的官方回復(fù),他們是這么說的,WebView 沒有 host 主機(jī)的概念,它只是在渲染一個(gè) HTML 文檔,并不是你想要訪問的網(wǎng)頁,所以不會(huì)有 Cookie 和 LocalStorage 的概念。那我們?cè)撛趺崔k?
由于 VSCode 它本身自帶 Node.js 客戶端,于是我們就想到,把這個(gè) Node.js 客戶端當(dāng)做代理服務(wù)器,轉(zhuǎn)發(fā) WebView 的請(qǐng)求。當(dāng)后端服務(wù)返回生成的源代碼后,再借助 Node.js 客戶端將源代碼寫入到本地工程。這樣,就實(shí)現(xiàn)了高低代碼混合開發(fā)的基本功能。最后我們還需要在 VSCode 里,實(shí)現(xiàn)內(nèi)置的賬號(hào)登錄功能,這樣才能讓請(qǐng)求帶上 Cookie,完成整個(gè)平臺(tái)的鑒權(quán)。
5. 低代碼平臺(tái)的相關(guān)問答
以下問答系演講結(jié)束后根據(jù)聽眾的反饋整理的,選取一些有代表性的問答分享給大家:
- 對(duì)于接口請(qǐng)求渲染數(shù)據(jù)的,這種是如何實(shí)現(xiàn)的?
- 在頁面描述 Schema 里除了描述頁面信息,還有一個(gè) Datasource 對(duì)象。Datasource 對(duì)象里新建一個(gè)數(shù)據(jù)源對(duì)象,描述接口請(qǐng)求數(shù)據(jù)的參數(shù)。頁面描述 Schema 通過 DSL 生成代碼時(shí),單獨(dú)生成一個(gè)數(shù)據(jù)源的 JS 文件。JS 文件里 export 導(dǎo)出一個(gè)對(duì)象,對(duì)象的每個(gè)屬性都是一個(gè)單獨(dú)的數(shù)據(jù)源對(duì)象。每個(gè)數(shù)據(jù)源對(duì)象有 fetch 獲取數(shù)據(jù)等方法,以及其他數(shù)據(jù)源相關(guān)配置項(xiàng)。每個(gè) fetch 方法內(nèi)部是將該數(shù)據(jù)源的參數(shù)傳給統(tǒng)一的獲取后臺(tái)數(shù)據(jù)的方法。給每個(gè)需渲染數(shù)據(jù)的組件配置數(shù)據(jù)源對(duì)象,生成的代碼包含雙向綁定數(shù)據(jù)。在頁面加載的時(shí)候,就調(diào)用數(shù)據(jù)源對(duì)象的 fetch 方法,給雙向綁定的數(shù)據(jù)賦值。
- 頁面代碼編輯出來后,持續(xù)維護(hù)這塊如何考慮的?方案是什么?
- 通過 DSL 將頁面描述 Schema 生成源代碼,這個(gè)過程是單向的。單向意味著生成的源代碼是只讀的,不可以編輯,只能被調(diào)用。如果對(duì)生成的源代碼改動(dòng),后續(xù)保存頁面生成代碼會(huì)覆蓋改動(dòng)。持續(xù)維護(hù)還是要走持續(xù)改進(jìn)和提升頁面搭建能力的方式。高低代碼混合的特點(diǎn),就是低代碼可以通過橋接方法調(diào)用高代碼。用戶在頁面搭建時(shí)通過橋接方法,直接調(diào)用本地相對(duì)路徑的 JS 文件。將包含復(fù)雜邏輯等需要經(jīng)常維護(hù)的業(yè)務(wù)代碼包含在這些 JS 文件里。低代碼搭建平臺(tái)始終主要做頁面、區(qū)塊等 UI 界面的搭建工作。
- 高低代碼混合開發(fā)中的橋接源可以理解為回調(diào)嗎?
- 低代碼平臺(tái)生成的源代碼存放在用戶指定的本地工程專有目錄下,與高代碼部分是隔離的。高代碼可以直接用相對(duì)路徑的方式導(dǎo)入或者引用低代碼生成的模塊,而低代碼要導(dǎo)入或者引用高代碼的模塊,則需借助橋接源。比方說,在低代碼平臺(tái)里定義一個(gè)橋接源,里面聲明高代碼模塊的相對(duì)路徑,或者 npm 依賴包的名稱。這樣在低代碼平臺(tái)的自定義方法里就可以導(dǎo)入高代碼的模塊或者引用 npm 依賴包。而傳統(tǒng)的低代碼平臺(tái),如果當(dāng)前提供的 API 接口不能滿足業(yè)務(wù),需引入第三方模塊,一般要先提需求,等開發(fā)完成后重新部署,再告知調(diào)用方式,整個(gè)鏈路會(huì)比較長(zhǎng)。
6. 總結(jié)和展望
華為云的低代碼平臺(tái)要想持續(xù)發(fā)展,就需要建設(shè)物料生態(tài)、平臺(tái)生態(tài)以及應(yīng)用生態(tài)。只有物料的雙向流通才能促進(jìn)物料生態(tài)的發(fā)展,除了組件、區(qū)塊之外,我們還要為用戶提供自助搭建可復(fù)用模板的能力,進(jìn)一步豐富物料的生態(tài)。我們要做低代碼的 PaaS 平臺(tái),利用 Web Component 技術(shù)以及 DSL 機(jī)制,為不同領(lǐng)域,比如辦公、零售、制造等,去創(chuàng)建定制的平臺(tái)。不僅要能夠生成桌面端應(yīng)用、移動(dòng)端應(yīng)用,還要能夠生成鴻蒙的多端應(yīng)用,擴(kuò)展我們的應(yīng)用生態(tài)。
低代碼的物料生態(tài)、平臺(tái)生態(tài)、應(yīng)用生態(tài),這三者不是互相孤立的,而是相輔相成的。我們要把這三個(gè)生態(tài)圈打通,形成合力,這樣下面這張圖,就不是三個(gè)圈,而是三個(gè)環(huán)環(huán)相扣的 8。
據(jù) Gartner 預(yù)計(jì),到 2024 年,低代碼應(yīng)用開發(fā)將占應(yīng)用開發(fā)總數(shù)的 65% 以上,將有 3/4 的大型企業(yè)會(huì)使用至少 4 個(gè)低代碼平臺(tái)進(jìn)行 IT 應(yīng)用開發(fā)。
另外,據(jù)不完全統(tǒng)計(jì),目前國(guó)內(nèi)外大大小小的低代碼廠商至少有 60 個(gè)以上,而且大廠商內(nèi)部的低代碼平臺(tái)可能還不止一個(gè)。作為企業(yè)數(shù)字化轉(zhuǎn)型的工具引擎之一,低代碼平臺(tái)必然會(huì)被越來越多的企業(yè)所了解并加以使用,使用的場(chǎng)景也會(huì)越來越豐富。我們?cè)陂_發(fā)或使用低代碼平臺(tái)時(shí),要清楚低代碼不能一蹴而就,而要持續(xù)迭代、持續(xù)演進(jìn),要不斷探索和拓展低代碼開發(fā)平臺(tái)的邊界。
作者簡(jiǎn)介
莫春輝,華為云主任工程師,華為云 Web 能力中心低代碼平臺(tái)負(fù)責(zé)人,AUI 前端框架負(fù)責(zé)人。2014 年加入華為,帶領(lǐng)團(tuán)隊(duì)開發(fā) HAE(Huawei Application Engine)前端框架,其底層核心是自研的面向?qū)ο蟮?JS 類架構(gòu),支持與 AngularJS 相似的數(shù)據(jù)雙向綁定,可靈活配置的系統(tǒng)、頁面、組件生命周期,以及支撐華為內(nèi)部 IT 應(yīng)用的高性能 UI 組件庫。2017 年 HAE 演進(jìn)成為基于 Vue 的 AUI 框架,并以落實(shí)體驗(yàn)一致性規(guī)范的要求,在公司各 BET 領(lǐng)域大規(guī)模推行,2019 年底發(fā)布了全新架構(gòu)支持跨端跨框架的 AUI 3.0 版本,2020 年推出同時(shí)支持 Vue 2 和 Vue 3 的 AUI 4.0 版本,2021 年開始負(fù)責(zé)華為云低代碼平臺(tái)研發(fā)工作。
除前端框架開發(fā)、低代碼平臺(tái)研發(fā)外,還參與制定公司的前端開發(fā)規(guī)范,擔(dān)任信息技術(shù)任職的評(píng)委、JavaScript 認(rèn)證考試專家組成員,系公司開源能力中心 Vue SIG 組織 Maintainer 成員。
活動(dòng)推薦
2022 年 6 月 10-11 日,GMTC 全球大前端技術(shù)大會(huì)(北京站)2022 將再度與您相約!前端業(yè)務(wù)架構(gòu)、前端 DevOps、前端性能優(yōu)化、IoT 動(dòng)態(tài)應(yīng)用開發(fā)、TypeScript、移動(dòng)端性能與效率優(yōu)化、前端成長(zhǎng)實(shí)戰(zhàn)、團(tuán)隊(duì)可持續(xù)建設(shè)、跨端技術(shù)選型等 15 個(gè)專題,最熱點(diǎn)的方向,解決你最關(guān)心的問題。更多精彩議題持續(xù)打磨上線中,點(diǎn)擊此處了解更多內(nèi)容。