在InfoQ 2019年舉辦的 GMTC 全球大前端技術大會上,螞蟻金服高級技術專家陳成發表了《螞蟻金服前端框架和工程化實踐》的演講,如下是本次演講摘要。
這是咱們的框架發展時間線。css
在 Umi 和 Bigfish 時代,咱們從刀耕火種的時代跨入了工業化時代。由於在此以前,用戶須要接觸不少技術棧和細節,在 Umi 和 Bigfish 中,用戶只要知道一個框架,剩下的所有不用瞭解。框架像一個魔法球,把各類技術棧吸到一塊兒,加工後吐給用戶,以此來支撐業務。html
在兩個框架合併以後,咱們的現狀是這樣:前端
這是一些螞蟻的內部數據:vue
目前來看,這個框架基本統一了內部的框架使用狀況,不只有不熟前端的 Java 開發,略熟前端的外包,還有資深的前端同窗。要得到那麼多同窗的承認,並非件容易的事。java
那麼,爲何咱們能成?我的理解,我以爲有幾個關鍵詞:
node
人是很是重要的一環,甚至比技術自己更重要一些。react
那麼別人爲啥要用你的框架?首先,框架要好用,這是最基本的;而後,使用者尤爲是資深的前端同窗,還得在這上面找到本身的成就感和 ownership,另外若是績效漂亮就更好了。總不能別人用你的框架,而後只有你本身一我的的績效好,那是不會長久的。webpack
咱們的解法是插件體系。git
框架不是憑空而來的,需求來自於業務,因此用框架寫業務的同窗每每能發現框架不足的點,他們能夠開發適用於本身業務的框架插件,反哺框架。若是這是通用需求,那就亮了。框架的內部開發羣有 100+ 人,包含大量來自業務線的同窗,這就是插件體系的好處,人人都能貢獻。爲了讓寫插件變得簡單,咱們給框架分了五層架構。程序員
包含依賴層、插件層、插件集層、應用類型層和部署模式層,你們可在任何一層均可貢獻代碼,
這是插件生命週期圖,包含:
大部分插件體系只會考慮 node 編譯時,咱們加上運行時和編輯時的支持,賦予了插件更大的能力。具體作了什麼就不展開了,沒個框架都不一樣,但作的事情其實大致一致,往上說是 html、css、js,往下說還有各類工具的配置,好比 webpack、babel、postcss、dev 中間件 等等。
下面來看具體如何寫一個插件,若是你們有寫過 vue-cli 的插件,會發現很相似:
咱們目前的部分插件,內部流程相關的就沒有列出來了,內外加起來應該有 100 多個了吧。
這是咱們的分工表,基本上涉及到了框架和業務的方方面面,不少事情都是由不一樣的人來負責,你們的參與度也不錯。
固然,人老是不夠的,不少子項都還處於招人狀態。
咱們的框架能成,我以爲另外一個重要的緣由是咱們不只作功能,還作業務和流程。我不清楚你們是如何走流程的,包括如何切換應用類型,如何和各類後端服務和平臺對接,反正咱們的仍是挺繁瑣的。程序員的時間浪費在這裏我以爲很不值,因此若是框架能解決這部分,應該會受到歡迎。
咱們經過 appType 和 deployMode 兩個維護來對接各類場景,用戶只要配 deployMode: node 就能對接 node 框架,改爲 java 就能對接 java 框架,背後的髒活累活交給框架作。
最後還有一個緣由是咱們作開源,我我的是比較熱衷開源的,把本身的實現徹底透明地展現給社區,包括以前寫的工具和數據流方案,也都是從開源作起,由於我以爲開源相比在內網閉門造車,能帶來不少好處。
另外,開源作地好,也更容易得到內部同窗的承認。包括以前作的 dva、如今的 umi,都不是一開始的內部首選,而是後來慢慢逆襲的。
這是咱們如今的框架大圖:
中間從下往上是社區開源、螞蟻開源、Bigfish 框架、應用發佈流程。
框架層主要就是咱們前面介紹的五層架構。
左上主要是資產市場,咱們提效的主要手段以前,這在後面會展開介紹。
左下是工程方面的配套設施,編輯器插件、測試、lint 工具等等。
右邊是對接的服務,經過框架插件,可實現配置式地對接外部服務,減小接入成本。
下面是咱們的一些拳頭功能。
今年因爲大形勢的緣由,咱們比較重研發提效,最好是一我的能幹 10 我的的活。關於提效,其中比較重要的是相同的代碼不要重複寫,要作提取和組件化。而資產市場就是作的這件事。爲了更有效地複用,咱們對資產市場分了四級:
咱們能夠藉助工具把區塊和頁面模板添加到頁面中:
經過 Umi UI(可視化方式)添加區塊的樣式。
區塊方案其實不是一開始就這樣,中間經歷了幾回迭代。
資產市場不會憑空運轉起來,或者說咱們作了資產市場,你們就會按照這套方案用起來。好比一個產品,設計師不按照約定的規範來設計,那資產市場就成了擺設。因此,這是一件自上而下的事情,而且得拉上設計師同窗一塊兒作,纔有可能作好。
在工具層面,咱們須要打通上下游,同時兼顧三類角色的同窗:
咱們在微前端方面也有一些沉澱,並在生產環境有大量應用。
關於微前端是啥?首先你們想到的多是一個解決多套技術棧共存的方案,好比首頁用 jQuery,訂單頁用 React,客戶系統用 Vue。這沒錯,可是一個相對狹義的理解。
一個問題是,若是咱們的技術棧一致,那是否就不須要微前端方案了?不是!
我對微前端的理解是,他不只是個技術方案,更是個解決流程、組織架構等問題的方案。
好比淘寶網,能夠簡單理解成有淘寶首頁、交易系統和幫助系統,這些系統是優先級的,而且在咱們人力有限的狀況下,咱們會把資深的同窗投入到重要的系統裏,不重要的系統咱們可能會經過外包或者購買的方式解決,可是一個底線是,不重要的系統不能影響重要的系統的運轉。
要實現這一點,目前流行的有兩種方式:
微前端的概念其實已經出來 3 年多了,但社區喊地比較多,給方案比較少,在生產環境應用地就更少了。
咱們首先是基於 SingleSPA。
圖中是咱們結合實踐總結出的關鍵技術問題。
以上問題,咱們都有解決方案,但可能有些還不完美,須要進一步嘗試。
這是部分問題的實現原理。
更多實現細節,能夠關注文章,分享以後咱們會公佈。
正如前面所言,咱們熱衷於開源,因此這套微前端方案在業務上驗證過以後,咱們就把他開源了:https://github.com/umijs/qiankun
這句話不是我說的,你們若是有發現更好的方案,能夠找 @有知 探討下。
做爲一個框架,你得有亮點;而做爲一個企業級框架,你得知足需求。而要知足需求,該有的功能就必須有,亮不亮無論,得有,不能讓框架成爲業務需求的瓶頸。
紅色的應用類型方面:
藍色的部署模式方面:
當前端框架成爲內部的一致選擇以後,就會被推着去作不少業務方面的事情,適配各類場景的需求。不過好在咱們有插件機制,上面大部分的需求都是業務方同窗經過插件和咱們一塊兒實現的。
除了拳頭功能,要作一個框架,還不得不在一些專題上有深刻的研究,不少知識點是須要完全搞透的,這樣才能知道如何設計更合適。
首先,咱們既支持配置式路由,也支持約定式路由。配置式是實際須要,約定式是理想:
功能方面咱們最早是參考 next.js 作的,但發現 next.js 只支持簡單的路由功能,因而本身作了不少擴展,
因爲咱們是集中式的路由組織方式,而且管控了路由的渲染邏輯,因此基於路由就能夠作不少事,
這個列表每次分享時都會增長,頗有想象空間。
這裏介紹一個你們可能感興趣的點,基於路由的按需編譯。就是好比咱們有 1000 個頁面,而調試時只要調其中的 5 個頁面,那隻編譯這 5 個就是最理想的。
這有幾種實現方式:
臨時文件的實現是這樣的,
雖然有些取巧,但簡單有效。
咱們的編譯是基於 webpack 的,誠如你們所料,啓動速度仍是比較慢的,尤爲是項目大了以後。爲了讓使用者體驗更好,咱們在這邊也作了不少嘗試,有正常的方式,也有不正常的方式。
正常的方式有:
進階優化的有:
「變態」優化的有:
性能優化是每一個框架和每一個前端都逃不開的點,從我 10 年前作前端起就關注這個點了,到目前方法有些變化,但性能優化依然很重要。下面咱們的一些嘗試,
目前爲止,由於瀏覽器的差別,咱們仍需處理瀏覽器的兼容問題。不過比第一代前端須要處理 IE6 的兼容問題已經好多了。
關於補丁方案:
編輯器插件是框架很是重要的配套設施,不少功能在框架層其實無法作,尤爲是用了大量的約定以後,編碼時會損失代碼提示方面的支持,利用編輯器插件就能彌補這一點。
舉兩個例子,
測試方面基本上和你們都同樣,包含單測、UI 測試、e2e 測試和集成測試,基本方案是基於 Jest + test-react-library + Puppeteer。
可是,你們都知道業務同窗很忙,沒有太多時間寫測試。因此咱們若是能有個基於路由的自動化測試方案,讓業務不寫代碼也能確保每一個路由都能正常運行,也是個不錯的選擇。
這是咱們的監控體系,有了數據,才能知己知彼,有的放矢。
分構建時和運行時。
構建時在雲構建容器層去生成構建報告,咱們自研的工具比較好辦,但就算在螞蟻內部,也仍是其餘工具的存在,好比直接用 webpack 作構建的,或者基於 webpack 封裝的。對於這些非自研的構建,咱們會用猜想的方式,來定位出他是有什麼工具進行構建。
數據層會跑大量的定時任務去作數據清理,提供夠展現層。展現層提供排名、大盤、版本分佈、競品分析、出錯預警等信息。
運行時沒啥特別的,你們的方法都差很少。有一點值得一提的是咱們會在雲構建平臺去自動申請埋點標識並在構建時自動注入,讓用戶免去埋點標識的申請,全部產品自動就會有數據支撐。
這是一些構建時的數據展示示例。
Bigfish + Umi 的內外結合的方式目前看起來還不錯,但畢竟是兩個團隊妥協後的方案,在咱們須要服務外部 ISV 時暴露了一些問題:
雖然底層都是 umi,但內外網同窗的使用方式仍是有很大差異的,致使咱們的方案對外時會有額外的成本,以及咱們本身在文檔等方面的投入上都須要作兩次。差別主要是:
因此,咱們要 讓內外網的框架方案保持一致。
修改後的這一版是我能預見的框架終態。