作者 | 馬一文

程序員中的一種,偶爾吟濕作對,潤滑萬物 ——子慕大詩人
前言
前端常常會在的業務中后臺開發數據統計圖表,對于類似 Echarts 這種配置性極強的庫,需要花費很多時間查看文檔, 一個項目中統計圖表大多情況下只占少部分,平時寫的不多容易忘記配置,重復開發的效率低。產品經理對于圖表的設計個性化明顯(今天看到一種樣式的圖表覺得也挺好,然后就想照搬到自己業務之中),同類型的圖表可能樣式不一,代碼又得重新寫。總歸給人的感受就是開發效率低,產品設計效率低。
在文章的開始我們先來看看一個前端平常在開發各種數據圖表時,可能經歷的過程,以 Echarts 為例:
打開 echarts 官網。
查看實例界面,參考需要實現的類似的圖例,找到合適的實例拷貝需要的實例代碼。
打開業務項目復制代碼,發現需要安裝依賴,也許通過 html 中 script 引入,也許通過模塊方式引入(這種情況下可能還需要配置一下 webpack 解決一些依賴優化的問題)。
發現細節上和 ui 或者產品原型不符,開始查找文檔配置,比如:軸線顏色,刻度顏色,內間距,提示器,文案模版等等。
做第二個圖表的時候,發現和第一個類似都是折線圖,但是這次是一個圖中有多個折線,ui 在細節上又發生了一些變化,然后重復上面步驟 4。
一段時間以后,另一個業務項目,再次需要做數據圖表。這個時候,想到以前做過,然后找到老項目對比圖表,拷貝類似的代碼,進行修改,發現細節不一致的地方又開始步驟 4。
因為每次做的圖表不一樣重復步驟 4、5 幾次以后,耗費的時間已經很多了,加上配置代碼本身就比較多,2、3個圖表就能讓代碼上一百行。經歷過幾次這樣的折騰以后,可能稍微熟悉了一下 API,但是仍然會覺得每次開發的效率好低。于是就有了今天所做的分享,下面進入正文。
方案
針對公司各個業務中后臺項目開發數據統計圖表的應用場景,為了解決以上兩個效率問題,我想到了通過下面兩個方向來做處理:- 抽象代碼減少應用代碼量,傻瓜式配置避免每一個開發者花費時間重復閱讀文檔 —— 提升開發效率。
- 統一圖表使用風格,減少一定程度個性化,提供圖表界面和對應組件代碼 —— 提升產品設計效率。
- 只關心更核心的配置、組件抹去配置細節、提升開發效率。
- 提升產品設計效率、省去設計選擇的時間。
- 缺少一定靈活性(抽離常用部分,犧牲靈活性,多用共性)。
- 公共圖表組件開發需要投入成本?。
實施
JS 組件庫
目的和方向已經明確,我們可能會第一時間想到,那肯定就是基于三方圖表庫做一次組件封裝,通過 npm 安裝依賴,最后再寫好文檔就行了。現在稱它為 JS 組件庫方案,那我們來考慮考慮此方案組件庫的一個實現和使用流程,以 Echarts 為例:- 新建一個代碼庫,安裝 echarts 依賴。
- 新建組件(比如一個折線圖組件)。
- 封裝組件參數,回調方法等。
- 如果要兼容 vue,angular,react,組件代碼需要寫三套兼容,或者通過代碼優化和構建處理,一套代碼生成多種框架組件。
- 定版本,發布組件庫。
- 寫一個網頁文檔并在網頁上展示實例。
- 業務系統安裝組件庫使用。
- 如果代碼需要升級或者修改 bug,需要重新修改組件庫,并發新版本,業務系統重裝依賴。
- 可能需要兼容多套框架,組件庫開發成本增加。
- 修改 bug 和庫升級都需要發版本,每一個業務系統都有可能需要在一個版本之后更新依賴,維護成本增加。
Iframe 方案
而我最初的下手點是通過 iframe + postMessage 來實施了這套方案,下面介紹一下此方案。此方案最終把一個個組件輸出為一個靜態的頁面,通過 iframe 的方式,嵌入到我們的業務系統之中,通過 postMessage 來傳遞數據、配置和事件綁定。先介紹一下大致開發和使用流程,而后對其優劣做分析。- 新建代碼庫,安裝 echarts 依賴。
- 新建頁面組件(比如一個折線圖組件)。
- 封裝組件參數,回調方法等。
- 打包輸出為一個個靜態資源頁面,發布到靜態資源服務器。
- 寫一個網頁文檔并在網頁上展示實例。
- 業務系統不需要安裝任何依賴,通過 Iframe 配置 url 引入組件,通過 postMessage 發送配置和數據。
- 如果代碼需要升級或者修改 bug,重新修改組件庫,打包更新靜態資源,業務系統不需要重裝依賴直接訪問就更新。如果存在變化比較大的類似組件,可以考慮輸出新版本,比如老版本是 xxx.com/v1/bar.html,新版可以定義為 xxx.com/v2/bar.html,互不影響。
優化
穩定性
Iframe 有個比較需要特別謹慎的地方就在于其穩定性上的問題,由于所有業務系統的圖表都指向到公共圖表項目,都需要對其進行訪問,如果出現了問題,那影響是很大的。由于業務系統是分散的,我們在發布新的公共圖表項目版本的時候,需要進行一輪測試,測試新版本,首先需要滿足的是不影響已有業務系統。于是,針對這兩個問題,我們一方面需要嚴格保障公共圖表項目的代碼質量,在代碼合并權限控制和人為 review 上需要格外重視;一方面可以同樣通過 Iframe 的方式,在公共圖表的文檔網站頁面加入一個頁面菜單、嵌入所有中后臺業務系統的相關頁面。由于我們中后臺統一接入了公司內部開發的 sso 權限登錄系統,因此可以根據當前的登錄用戶和他的權限,看到他所能夠看到的業務系統的圖表統計相關的頁面。那我們給一個測試用戶配置所有業務的權限,就能通過公共圖表系統本身查看到所有業務相關界面,以此來做測試驗收。也因為如此,公共圖表項目本身不僅提供了頁面組件給業務中后臺系統使用,也同時集合了所有業務系統的數據統計界面,變成了一個真正的數據大盤。到此我們的方案就是一個完整的公共圖表數據大盤。資源大小
在靜態資源大小方面,每一個 html 組件,只引入了一個三方圖表庫和組件本身的一小段 js 代碼,并沒有引入任何框架,盡可能的減少文件大小。迭代原則
首先做封裝是有成本的,并不是一開始我們就寫好所有的組件庫,而更多應該是在開發需要某一種圖表時,再考慮進行封裝,封裝的同時不僅要考慮當前版本使用,也要盡量考慮通用性和后期其他項目使用的情況。純個性化配置
當然很多情況下需要個性化配置我們的圖表,既然當前已經有了公共系統,如果遇到個性化的圖表,難道又要讓業務系統去安裝 Echarts 依賴,然后以舊的模式寫配置嗎?所以,在公共圖表項目內部也提供一個純個性化配置的圖表,也就是沒有任何多余封裝的組件,配置信息完全需要業務方寫好,組件直接調用生成,不做任何處理。這樣我們依舊不需要管理依賴,仍然也只是關心配置。界面優化和約定
如何統一用什么樣式的圖表,這需要產品、設計和研發一起商量做好約定,這塊是需要投入成本的。多圖表庫支持
上周在公司內部分享的時候,被問到可以支持多庫嗎?確實不排除后期需要多庫的情況,或者某些圖表庫不支持我們想用的功能,因此在代碼架構配置中做了處理,已經支持多三方圖表庫存在的情況,具體內容可以看 github 倉庫。Iframe 方案可能會被吐槽的一些問題
- 阻塞父頁面加載:由于單頁面框架內使用 Iframe 大部分都是在框架本身生命周期中創建節點,所以并不會阻塞業務本身。
- 安全問題:因為我們的圖表項目是自己寫的,并且是純靜態資源,沒有接口的輸入,也沒有任何業務,因此沒有任何攻擊的價值。
- 性能低下:因為在 PC 端這樣的場景之下,Iframe 本身會帶來的性能問題是微不足道的,并且一個界面之中的圖表大部分情況下是不會超過 10 個的,即便有 10 多個,也都并不會導致卡頓。配合上緩存策略,圖表的加載實際也很快。
代碼展示
業務代碼在使用組件時,只需要大致下面這些代碼,不需要安裝任何依賴。倉庫演示
https://dashiren.cn/public-chart/dist/index.html
倉庫地址
https://github.com/zimv/public_chart
結語
基于我們需要解決的問題,選擇哪一種方案,其實都可以,只是剛好我偏向于 Iframe。從發現問題到解決問題,從提出想法到實施落地,以上便是全部內容,希望能給大家帶來一些啟發,今天的分享就到這里。
全文完
以下文章您可能也會感興趣:
Mysql redo log 漫游
一個 AOP 緩存失效問題的排查
小程序開發的幾個好的實踐
Web 開發打印總結
小程序中 Redux 的使用
數據可視化過程不完全指南
小型大寫字母的用武之處
React Native 項目整合 CodePush 完全指南
震驚!JavaScript 竟然可以類型推斷!
ConcurrentHashMap 的 size 方法原理分析
我們正在招聘 Java 工程師,歡迎有興趣的同學投遞簡歷到 rd-hr@xingren.com 。