华人澳洲中文论坛

热图推荐

    闲鱼大终端UI组件库——FishUI建立之路

    [复制链接]

    2023-2-15 09:15:40 18 0

    配景
    跟着闲鱼前端架构的不停演进,一些症结技术设施需求结合业务特点逐渐自建,技术计划也要拥抱社区来晋升可扩展性。一方面, 闲鱼跨端开发框架kun 让前端开发者使用JS/CSS/HTML便可交付终端页面,同时统筹了静态性和高机能,另外一方面,前端UI框架也正从团体 rax 逐渐转向社区 react 计划。在这个大配景下,环抱 kun 和 web 两个容器的跨端组件建立也势在必行,因此 Fish UI 应运而生,它将片面拥抱 React 生态,并借助 kun 容器的才能,为闲鱼终端开发者提供一套高易用性和不乱性的跨端(kun & web)UI组件库。
    FishUI 的最大的技术翻新点在于跨端,它经过跨端组件的方式对齐 kun 和 web 两个容器的体验规范,让使用者更为专一于业务逻辑而非容器差别,从而完成为业务开发提效的指标。环抱着该翻新和指标,一些可预知的技术困难也随之泛起,好比组件库的工程构造如何组织、分端构建如何做、开发标准是甚么样等等,这些问题将在下文中一一失掉解答。
    总体设计分层设计
    Fish UI 作为兼容 kun 和 web 两真个组件库,包孕底层的kun容器组件和下层的跨端组件,其分层构造大抵如下:


    其中【跨端组件】一层是 Fish UI 最下层的封装,是抹平 kun 和 web 容器差别的一层,同时也是业务开发者使用频率最高的一层。
    现实状况是【跨端组件】要尽量依赖底层【w3c标准组件】组合扩展而成,要足够丰硕,而【kun 扩展组件】一层则但愿尽量做薄,由于其与kun 容器强绑定,是为理解决特定场景问题而发生的,不具备通用性。
    本文后续也次要讲授环抱【跨端组件】这一层的相干建立内容。
    跨端设计
    FishUI 最中心的特征在于【跨端兼容 kun 和 h5】,也是与其余组件库最大的差别点。
    通常状况下,业务开发者需求手动判别环境,分别完成两个容器对应的代码,好比渲染一张图片的代码如下:


    经过 FishUI,咱们冀望的调用形式应该是这样


    经过比较,能够看出 FishUI 跨端设计的中心功用在于:
    ? 自动按照 window.kun 判别环境,履行对应环境代码
    ? 自动抹平 kun 和 web 两真个属性差别,无需用户手动处置
    ? 对外提供一致的 TS 接口声明
    ? 增加模板代码量,晋升代码简洁度
    因此,FishUI 跨端组件的分端设计大抵如下(以 image 为 例):


    技术选型言语
    咱们选择了 react + typescript + moduleCSS 作为组件开发言语。
    其中款式计划咱们使用了 moduleCSS,次要缘故是为了不多人合作开发时存在的款式净化问题。
    虽然 【less/sass + 一致前缀】也能够解决款式净化问题,好比规则一切组件类名都是 fish-ui-xxx 的格局,其余款式都在该类名的作用域下。然而因为没有对类名进行 hash ,致使组件使用者在开发过程当中能够经过类名来覆写组件外部元素款式。这个行动是一把双刃剑,益处是组件款式扩展性好,使用者遇到组件款式不知足需要,很容易覆写组件外部款式。害处则是组件失去了向后兼容的特性,好比使用者自定义了 .button-inner-text 款式,起初某天 Button 组件外部dom构造变卦,或者类名调剂了,一切使用者的自定义款式都会生效,容易形成线上问题。
    衡量利害,终究肯定了 moduleCSS 的计划,包管组件外部款式,不允许使用者随意侵入,假如有自定义款式需要,能够经过减少组件属性,或者 css vars 的形式来给使用者启齿子。
    目录构造
    采取了 monorepo 的单仓多保证理架构,一个组件对应一个 npm 包。
    比拟于【多仓多包】和【单仓单包(多组件一个包)】,monorepo 同时具备下列几点劣势:
    ? 使历时,反对按需引入单个 npm 包。
    ? 开发时,根据目录隔离,各包独立迭代发版,防止核心化的合作形式,同时统筹一次性改多个组件的开发体验。
    ? 在团体外部搭建场景中,目前只能做到包粒度的 treeShaking,因此更细粒度的多包会比一个大整包会更有加载劣势。
    至于单个 package 的构造,咱们则间接遵守了团体内 ICE PKG 的标准,它提供了单 React 组件的开发/调试/构建/发包的全套计划。


    依赖办理
    总体选用 pnpm 进行依赖包装置办理,使用 lerna + nx 进行多包版本办理 & 脚本履行办理。
    保证理计划 pnpm
    在 monorepo 场景下,npm/yarn 等保证理器等都有本人的 workspace 标准,关于多包的依赖,能够扁平化晋升到最外层的 node_modules 目录下,解决了依赖反复装置的问题,然而又带来了其余的问题:
    ? 幻影依赖:因为依赖扁平化到最外层之后,包 A 能够间接 import 包 B 的依赖。
    ? 分身依赖:指多包依赖了某个包的多个版本,只要一个版本能够晋升到最外层 node_modules 下,其余版本仍是会嵌套装置,致使反复装置,如下图中 B 包就被装置了屡次。

    ? 多名目反复装置:好比某个依赖在 10 个名目中使用,就会有 10 份代码被装置到磁盘中。
    以上问题,均可以在 pnpm 中解决:
    ?多名目反复装置问题:pnpm 会全局缓存曾经装置过的包,而后 硬链接 到名目中的 node_modules 目录下,防止了反复装置的问题,且大大晋升了装置速度。
    ?幻影依赖 和 分身依赖问题:pnpm 装置的依赖并不是是扁平化构造,而是经过 软链接 的方式链接到 node_modules 目录下的 .pnpm 中,这样就同时防止了幻影依赖和分身依赖的问题。
    lerna 为对比通用的 monorepo 办理工具,既能进行版本办理,又能够统筹构建任务流、公布包等流程方面的办理,曾经是业界十分主流的多保证理计划。
    鉴于单npm包修正后的版本更新,咱们不但愿影响到其余未修正的 npm 包的版本,因此咱们版本办理战略采取 independent 模式


    另外,lerna 6.x 能够配合 nx 来优化全部任务流程,详细表示为:
    ?缓存脚本后果,防止反复履行,能够明显晋升脚本运转速率。
    ?基于多包的拓扑构造来履行脚本,好比 a 包 start 履行前,会自动先运转依赖的 b/c 包的 build 命令。
    ? 能够提供图形化的多包依赖拓扑图。

    分端构建包管了业务侧不会加载冗余代码,晋升页面加载体验。
    默许状况下,每个组件都采取了 ICE PKG 自带的构建形式,使用 rollup + swc 来构建出 esm 产物。
    终究一个组件 npm 包的入口文件 index.js 大抵如下:


    由上能够看出,组件自身没有提供分端构建,而是在运转时经过window.kun来区别是 kun 环境,仍是 web 环境,从而履行对应环境的代码。
    这关于极致的加载机能是个不克不及让步的微小问题,因此咱们在外部一致的构建工具fish-app中,减少了分端构建的才能,这样在一切业务场景中使用 Fish UI 组件的时分,终究产物就只会包孕特定环境的代码。
    分端构建的中心逻辑是:
    ? 在 webpack 构建过程当中,新增自定义 loader,在该 loader 中使用@babel/parser剖析源码 ast,并将 window.kun,转化为 true 或者 false(取决因而否是 kun 环境)。
    ? 而后结合 webpack 的 treeShaking,就会自动剔除 deadCode。
    下面的代码,在构建 kun 环境代码时,通过第一步 babel 的转化后,就是这样:


    而后通过第二步 webpack 的 treeShaking 后,变为这样:


    这样在特定环境,就只会加载对应环境的代码,完成了分端加载。
    自动化测试
    单元测试是保障组件品质和不乱性的首要一环。
    ICE PKG 自身并无提供自动化测试相干才能,因此咱们基于 React 民间保举的工具链来增补单元测试的部份,使用 jest 作为测试框架,使用 React Testing Library 作为React组件测试工具集。
    Enzyme 也是十分流程的 React UI 测试工具,然而咱们仍旧采取了 React Tesing Library 的次要缘故是:React Testing Library 更为推崇站在用户的视角去测试,Enzyme 则更为带有开发者视角,从两者的 api 设计上就能看出一二,React Testing Library 简直屏蔽了一切侵入到组件外部完成的api,正如用户同样,用户是不会在意组件的外部的 props/state 是如何变动的,只要开发者在意。所以 React Testing Library 成了咱们终究的选择。
    基于以上,一个简略的组件单元测试,会是如下的成果:


    代码标准
    代码标准在多人合作开发的场景,能够大大晋升代码的可保护性,从而包管高效响应每一个次的业务需要。
    咱们遵守闲鱼前端一致代码标准,包罗如下:
    ? 编码标准 (包孕 HTML/JS/TS/React 等规定)
    ? co妹妹tlint 规定
    这部份也能够参考 f2elint,这是《阿里巴巴前端规约》的配套 Lint 工具,能够为名目一键接入规约、一键扫描和修复规约问题,保障名目的编码标准和代码品质。
    API 设计标准
    除了代码标准外,咱们还商定了组件 API 的设计标准,好比 api 命名格调等,无利于造成一致的使用心智,晋升易用性
    组件 api 次要包孕两部份:
    ? 固定属性,每个组件都要有的属性
    ? 自定义属性,组件独有的属性
    保存 className 和 style 属性,便利款式使历时扩展。


    自定义属性


    其余 API 设计倡议
    ? 组件应该拥有可组合性(相似 HTML 标签,拥有语义化作用)

    ? 组件的受控与非受控
    ? 关于受控属性,该当提供相似 value + onChange 的组合
    ? 关于非受控属性,该当提供相似 defaultValue 属性
    ? 组件应该拥有可扩展性
    ? 公道使用 children 和 renderFunction
    ? 公道使用缩写
    ? 非须要不缩写,增加误读率
    ? 然而关于一些常见的缩写规定能够保存,好比 text4Title,date2String 等。
    文档站点是展现组件库的窗口,良好的文档能够晋升组件库总体的易用性。
    在 FishUI 中,单个组件的文档产出为 markdown 格局,咱们采取 docusaurus 来静态生成组件的文档站点,次要基于下列几点缘故:
    ? 基于 React 技术栈,社区插件多,生态成熟,好比 React/Webpack/Midway 等泛滥站点都是基于 docusaurus 构建。
    ? 扩展性好,反对 mdx,允许在 markdown 中无缝拔出曾经 jsx 代码,还能够 import 组件。
    ? 反对文档搜寻,基于 algolia。
    ? 跟团体外部结合对比好,好比
    ? 是 ICE PKG 的默许文档计划
    ? DEF(团体前端工程基座)中有基于 docusaurus 的 FaaS 动态站点计划
    除了 docusaurus 默许提供的 markdown 渲染才能外,咱们还扩展了如下才能:
    ?Playground,能够编纂组件示例代码,并实时预览
    ? 原理是基于@babel/standalone来对用户代码实时进行编译,而后使用 new Function 静态履行编译后的代码。
    ?KUN 和 h5 的扫码预览才能
    ? 原理是分别构建组件示例在 kun 和 h5 下的产物,并生成二维码注入到本来的 markdown 文件中。
    终究单个组件的文档如下:
    难点和应战
    跟着组件开发进度不停推动,也袒露出了开发层面的一些问题:
    ? React框架的事情机制不反对在kun标签上绑定自定义事情,例如不反对在 kun-image 标签上间接减少 onAppear 属性。这个问题能够手动调用 dom 的 addEventLisenter 来绑定,也是目前咱们选择的解决形式,然而这类方法稍微繁琐和蠢笨,后续方案采取运转时计划,hack 全部 React.createElement,劫持组件的props并静态绑定事情和减少属性。
    ? 跨真个属性适配问题。kun 和 web 二者自身就有得多实质差别,一些属性能够 kun 向 w3c 规范适配来解决,然而有时分强行抹平这些差别将付出很大的开发和保护代价,此外 kun 从一开始就不试图去达到齐备的 w3c 规范,因此咱们的跨端组件允许针对 kun 和 web 离开设置属性,终究能达到统一的成果便可。
    ? 跨真个单测问题。基于 jest + jsdom 框架,单测无奈掩盖到 kun 环境,kun 真个组件大可能是 kun 标签的桥接完成,因此这部份单测临时由客户端包管,后续方案前端减少对 kun 环境的 mock 。
    除了以上开发层面的问题外,名目推动的最大难点是在闲鱼终端融会的初步阶段,客户端和前端同窗对待问题的视角存在差别,技术栈也未彻底对齐,因此繁多组件很难由繁多同窗独立担任,致使开发保护和沟通的本钱较高。此外为了包管组件库的规范化才能,需求少量的标准束缚和工程才能撑持,好比 api 设计标准、交互视觉标准、代码开发标准、一致的脚手架才能、一致的 CI/CD 才能等,这些内容并非一步到位,而是跟着各方合作者的理论和反馈而继续迭代完美,这个进程注定会十分迂回。
    总结与瞻望
    FishUI 刚刚起航,目前咱们产出第一批组件刚刚进入业务试用的阶段,FishUI 的引入将使得跨端工程的开发比拟以前大大提效,次要体现为:
    ? 跨端体验规范更为一致
    ? 跨真个模板代码量增加
    ? 跨端适配问题变少,开发时间缩减
    然而放眼将来,FishUI 还有依旧得多的任务要做,包罗:
    ? 增强与视觉交互的联合
    ? 跨真个开发和调试体验优化
    ? 多前端框架反对
    ? 更多的业务场景落地
    另外,跟着闲鱼终端融会的不停深化,咱们冀望 FishUI 可以成为前端开发者和客户端开发者学习彼此的试验场,终究能有更多终端开发者借助 FishUI 的场景生长起来,并助力 FishUI 更好地向前迭代。总之,FishUI 将来的路还很长,置信终有一天,它将泛起在闲鱼终真个各个线上场景,真正助力闲鱼业务高品质向前开展,敬请期待~

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    返回列表 本版积分规则

    :
    注册会员
    :
    论坛短信
    :
    未填写
    :
    未填写
    :
    未填写

    主题32

    帖子35

    积分170

    图文推荐