关于可视化组件技术选型的思考
名词定义
基础组件
StandardChart所包含的标准范式组件,业务场景中真正使用的一般就是折柱饼等有限的几类图表。
业务组件
和特定业务绑定,具有特殊的交互和UI需求。
比如:海外矩形树图、F10股权图、行情图等。
注:有的业务组件可以通过SD配置得来,比如火焰图。
StandardChart的弊端
个性化需求难以修改:
因为底层是基于ECharts的,所以添加和修改任何需求,都必须遵循其设计,且因为ECharts的复杂度高,需要开发者了解大量的前置知识。
关联性影响问题:
同样是由于ECharts的复杂度高、组件之间关联性强,因此容易产生修改A组件导致B组件出问题的情况。之前也出现过多次改完上线后,发现影响了其他功能的问题。
难以AIGC:
目前基于SD的HiPilot生成可视化代码,需要LLM了解的上下文太多了,导致难以通过LLM直接生成可用的代码。
粒度太大:
SD所有图表都在一个库中,整体比较臃肿,实际上业务方往往只需要一个折线图,但是不得不使用包含所有图表的CDN(类似早期ESB模式的SOA)。
而且这样也不利于KAmis的单个组件单个库的设计机制(Figma2Code要求一个组件一个仓库)。
方案选型标准
什么情况下基于SD开发,什么情况单独写?
方案选型的本质就是做权衡和取舍。当A方案的成本和收益低于B方案时,B就是更好的选择。
回顾我们之前的需求,可以总结出如下权衡点:
技术权衡点
- 为了契合ECharts的程序流程,改动一个小需求需要大量的开发成本
- 和ECharts的设计冲突,在当前架构下无法实现
- 和ECharts的设计冲突,会带来大范围的影响和不可控性
业务权衡点
业务组件 ∩ StandardChart中没有的,就单独新写。
高定需求的基础框架
(TODO)技术选型
目前暂定D3 + ZRender
不过ZRender有个潜在的问题:LLM可能并不了解这个渲染库。
关于UI框架,是不是选择React技术栈更好一些?
需要解决的问题
如何解决公共函数/包的修改导致其他组件受到关联影响的问题?
shadcn/ui的模式?
或者公共的函数和包,单独打包为npm,通过安装npm包的形式进行使用。
如何解决依赖的库的版本升级问题?
比如D3、ZRender升级,那么已有的所有组件是否都要升级?
需要包含的功能
机制类
机制类的内容,应该由脚手架/框架自动生成抽象接口,开发组件时再进行实现。
生命周期:
core统一进行定义。
主题机制:
这个应该是每个库独立实现,不好做到代码实现层面的统一,只能做到接口和入参规范层面的统一(抽象接口)。
AIGC封装机制:
在HICharts这一层实现,可以AI自动生成封装代码、自动接入。
Timeline机制:
帧循环 + setOption重绘机制(抽象接口)。
代码组织形式
初期可以先不考虑,每个需求独立一个项目进行开发,待确定有内容是可抽取的,再抽象封装为通用的包。
参考下其他优秀的开源库的方案。
MonoRepo?
分包?
pnpm Workspaces
Yarn + Lerna
Demo开发形式
StoryBook?
打包&发布方案
方案一:
每个项目新建一个PaaS流水线。
方案二:
只创建一个流水线,自动增量发布,参考KAmis组件的打包方案。
应用方案
CDN引入方案
SDK嵌入模式(需标准化)
MCP(开发人员和运营人员的场景)
当前代码库的规划和整理
(TODO)目标与收益分析
StandardChart
缺少抽象层:缺少清晰的抽象接口定义,导致扩展实现不统一
命名问题
theme目录的规划不合理,未体现业务特性。
耦合度高:使用依赖注入降低组件间耦合
缺乏单元测试
setTimeout的问题
TODO、FIXME
分支整理下。
通过Builder模式封装范式配置,简化业务方的自定义组件配置(VISALL其实也可以这样弄):
1 | |
VISALL
分层逻辑不明确:
需要有一个明确的模块边界和接口定义
数据层(包括定义和预处理等,名字dataProcessor建议改一下)、领域逻辑层、视图层和控制层
职责划分不清:
API 模块中混合了多种职责,包括DOM操作、核心渲染逻辑和布局管理
MainStandardChartView.ts职责过多
耦合度太高:
引入依赖注入的思想,参考InversifyJS
数据预处理模块引入Zod提升程序质量和可维护性与可测试性,增加对属性值类型的验证。
缺少统一的错误处理工具和规范
缺少单元测试
需要提供更多的开发者工具和文档