介绍:无论是前端刀耕火种的jQuery/YUI时代,还是基于数据驱动UI的React/Vue时代,材质/组件一直是前端永恒的话题。基于大量重复逻辑的封装,可以明显提高前端UI的构建效率,简单直接。因此,无论技术栈如何变化,素材工作是每个前端团队首先要解决的。无论是前端刀耕火种的jQuery/YUI时代,还是基于数据驱动UI的React/Vue时代,材质/组件一直是前端永恒的话题。基于大量重复逻辑的封装,可以明显提高前端UI的构建效率,简单直接。因此,无论技术栈如何变化,素材工作是每个前端团队首先要解决的。2021年看现在,基于React/Rax体系的基础组件体系已经基本完善,包括蚂蚁好的设计语言AntDesign[1],以及集团基于DPL的快速定制的Fusion[2](阿里中-后台UI解决方案,已经开源),基础组件层面的功能越来越完善,各业务团队之间在这一层面的底层重复建设也越来越少,这是一个很好的结果。但是,在业务组件系统的建设中,仍然存在百花齐放的情况。由于技术栈(可视化、小程序等)的不断扩展,业务组件的开发还存在工程系统混乱、开发环节不合理等诸多问题。问题。来到企业智能这5年多时间里,经历了团队的素材系统,从最初的Arale/kuma,到基于react-component的UXCore/SaltUI,再到现在与Fusion的全面融合。基础层面的变化也带来了业务组件领域工具链的不断变化。写这篇文章,一方面是记录下自己在这方面的一些工作和思考,另一方面也希望能得到社区大家的一些宝贵建议,从而得到一些新的启发。1、一个业务组件应该开发多少次?1.难点有一天,同事A找到我,说TA在业务中需要构建一个业务组件包,涵盖PC端、小程序和对应的可视化组件。当时我在做一些前端业务能力建设的相关工作。所以想征求一下我的意见。这个问题看似很简单,但实际分析后发现问题很多。首先使用飞冰[3](iceworks,阿里GUI构建工具)+深度脚手架模板(深度来自企业智能用户体验团队)开发PC业务组件。好处是可以和Fusion深度对接,发布更方便同步素材到Fusion对应的深层站点。小程序/移动组件。当时,基于Rax的动态小程序组件解决方案FusionMobile和DeepMobile刚刚起步。业务组件的开发没有自己的标准。gdt-utils托管。可视化组件是Lego(阿里巴巴企业级可视化平台)团队提供的vdev工具链。当时还有一个问题就是PC端是基于React框架,而小程序/移动端是基于Rax框架。也无法在可视化开发时通过初始化一个包来完成PC和小程序的开发。综上所述,开发一个涵盖三种模式的业务组件,需要适配和学习三个工具链,初始化四个包,发布四个npm包。在后续的使用中,用户需要记住这四个包名及其对应的使用场景,并至少在两个地方查看它们的用法。同时,在维护阶段,PC端和移动端相似的模型、请求、数据处理逻辑不能复用。如果你想重用它们怎么办?抱歉,那么您需要发送另一个工具包以在多个包之间进行传输。这些无形中增加了开发一个业务组件的成本,同学们的精力都消耗在了这些框架、封装、联调的过程中。2.虽然集成开发的结果表明这样可以完成开发,但是从上手门槛和开发效率来说确实差强人意。一个是需要写很多文档来澄清这件事,另一个是仅仅为了开发一个业务组件需要这么大的成本真的是一个好的解决方案吗?那我们能不能不要那么多东西,一个工具链,一个包就可以解决所有问题,不是很好吗?这一切都很好,但在我们真正做到这一点之前,还有很多问题需要解决。最大的问题是如何将Rax和React这两个框架有机的结合在一个工具链上。这似乎不是一个很难的问题。看来只需要将之前的React和Rax的webpack配置拿过来,分别运行即可。但是集成之后,有些东西合二为一了,比如demo文件。对于一个想要融合开发的同学来说,自然不会想写几个几乎一样的demo,只是因为不同的运行框架带来的参考是不同的。类似于可视化组件中的prototypeView文件,该文件用于在乐高设计器中渲染组件。这里需要一点乐高组件开发知识。prototypeView文件的大致代码构成如下:本次设计在可视化组件中。是在React框架的前提下设计的,之前的实践没有问题。但是集成开发之后,就像上面代码中的注释一样,如何驱动一个React组件和一个Rax组件混合打包,并且能够正常渲染,需要一个解决方案。其次,从工程的角度来看,应该选择什么样的工具链来实现这种集成开发能力?显然,目前的每一个工具链都不具备直接实现它的能力。是选择其中一项进行增强,还是另起炉灶将三种能力结合起来?各有利弊,需要权衡。还有一点必须要考虑的是如何尽量减少对开发者初心的改变,尽可能的保持Fusion素材能力的匹配(比如同步到Fusion站点),这样开发者就可以随着迁移尽可能少的成本想出一个新的开发模式。在确定了这些问题之后,我们着手通过融合开发来解决这个发展困境。3.着手解决确定目录结构的问题。首先,我们需要确定FusionDevelopmentKit(以下简称“FusionPack”)的目录结构:从源码结构来看,我们基本遵循可视化组件的文件结构,满足了可视化的特殊需求一方面的组成部分。需求(如setter的配置,设计状态的渲染等),另一方面,通过指定package.json的main字段,直接引用包名调用组件的需求可以也得以实现。技术栈上充分利用了ts和scss,与Fusion组件对齐,方便使用scss变量和css变量。在构建产品方面,我们结合了几个工具链产品的特点。首先我们构建babel翻译的es5文件和相应的声明文件,供一般项目使用。其次,构建预留的import/exportes模块,用于需要包体积的项目做treeShaking。然后,将对应的md构建成浏览器可以直接预览的demo,放到build文件夹下与Fusion组件对齐,然后将lib文件夹下的文件复制到build目录下,方便乐高搭建和识别(乐高搭建时会直接进入build目录下的view.js和view.mobile.js文件)。工具链的选择在工具链的选择上,我们最终选择了乐高的开发包vdev作为扩展的基础。这样做的考虑是可视化组件整个开发系统比较重,而且不是插件,所以抽取和迁移成本高。.其次,相对于其他两个工具链,vdev是在一个大团队的基础设施部门维护的,沟通协作相对简单。我们并没有完全重建剩余的部分,而是尽可能复用现有构建脚本系统下的插件。我们先修改vdev,使其支持build-scripts相关系统的调用,其余的开发都是基于build-scripts下的plugin开始的。最终链接如下:pc.json大致如下:在开发过程中,我们已经确立了一个原则。基于一般规则下PC、Mobile、小程序的预览,我们尽量通过官方的build-plugin-component来实现。不支持的功能或BUG通过共建完成或修复,而对于fusionpackages特殊规则,如集成需要的特殊配置处理,post-build文件传输等逻辑,通过build-scripts下的post-sequence插件系统(我们这里命名为build-plugin-vdev-component)可以配置前序插件定义的配置,增加进一步处理的特性。这样不仅减少了后续的维护成本,还可以通过build-plugin-component帮助到更多的业务。确定基本架构后,进一步定义了fusion包相关的npmscripts:start:用于启动可视化部分的调试,包括设计器和预览startPC:用于启动PC部分的调试startMobile:用于启动移动端web部分调试startMiniapp:用于启动移动端部分调试build:用于生成上述构建产品。除了start,其他都是通过build-scirpts插件系统完成的。确定了调试要解决的主要问题的总体框架后,就开始具体的开发过程。start相关的流程不需要做太多修改,主要是将组件名别名到对应入口(PC为view.tsx,Mobile为view.mobile.tsx),剩下的主要是完成build中的缺失-plugin-component功能,比如Rax部分对scss的支持,对inlineStyle配置的支持。值得一提的一点是关于演示文件中jsx的处理。我们都知道jsx是React提出的js的增强语法。用于描述模板,完全使用js语法。其实浏览器是无法直接识别的。一般的处理方式是通过babel转换成对应的transformation语法。比如转换为:对于jsx标签比如会转换为React.createElement("div")。这在单一框架下是没有问题的,但是既然fusion包里的demo在PC端和移动端复用了,是不是应该转成React.createElement或者Rax.createElement呢?显然,这是不合适的。他只能决定是启动和调试PC端还是小程序,而Rax官方其实建议不要直接引用全量的Rax变量,而是按需从Rax变量中加载相应的API。比如createElement,写法自然有区别。所以我们在demo文件的写法上打了一个交集,大致是这样的:demo文件的写法是站在pc的角度,引用的依赖是react的Component和createElement,以及基础的组件库@ali/deep。启动小程序调试时,react别名为rax,@ali/deep别名为@ali/deep-mobile。而jsx相关的,比如会转化为createElement("div"),从写法上保证了编译后的可行性。构建主要要解决的问题是在构建过程中,要同时构建PC端和Mobile端的demo,而build-plugin-component只能启动Rax或者React的构建,显然不能满足我们的需求。脚本中间有很多重复的操作,比如增删文件夹等等。我们选择使用build-plugin-component的rax部分,在后续的pluginbuild-plugin-vdev-component中再创建一个Reactwebpack任务,同时完成PC端和Mobile端的demo构建。在构建es5文件的时候,也遇到了jsx的编译问题。由于源码中包含一部分react文件和一部分rax文件,所以启动时也可以根据入口的依赖链设置babel配置,但是构建时源码不对。该文件只是通过babel而没有webpack,所以我们需要使用其他方法来处理它。我们采取的方法是先分析每个文件的AST,从文件的packagereference分析文件是React还是Rax组件,然后使用不同的babel配置进行编译。为什么不按照上述demo中的方式处理呢?原因是demo方法强依赖createElement的引入,写法比较受限。在源码部分,我们希望能让用户有更灵活的使用方式。这样ProCode下的场景可以正常使用,但是乐高环境下不行,主要是prototypeView.tsx文件的处理。正如我们上面提到的,这个文件将同时介绍React和Rax组件。虽然在设计状态下,实际上只渲染了一个组件,但是在声明组件类时会用到一些API,比如Rax.forwardRef。结果,不做任何处理,在设计状态下,会报错,因为缺少API而无法使用。乐高的componentsavebuild,和一般的Procodeproject,都是针对每个组件单独构建的,组件不知道是要用在乐高PC(React环境)还是乐高小程序(Rax环境)的时候建成。因此,我们在本地构建组件时会额外生成一个prototypeView.rax.js。这个文件的内容和构建出来的prototypeView.js没有本质区别,只是提供了一个额外的乐高入口来打包构建。乐高检测到,当一个fusion包为这两个文件入口配置了不同的webpack别名时,就会将rax相关的api别名转移到prototypeView中remaxjs社区的rax-compact包中。).在prototypeView.rax.js中,将react相关的api别名为rax/lib/compact,用于乐高小程序设计状态(Rax环境)的展示。4、最终效果最后,我们将业务组件的开发和使用流程统一为一个包(集成vc包),一个工具链(vdev:初始化、调试、发布),@ali/deep和@ali/deep-mobile这两个基础组件包实现了按需加载和编译(Fusion/Antd也支持)。使用时无论PC端、小程序还是可视化部分都可以引用同一个包,无需记住不同的包名和对应的平台。一般情况下,我们可以直接引用包名导入PC部分,通过es/view.mobile(或lib/view.mobile)引入mobile/applet部分。另外,这里我们也在package.json中注册了相应的入口,这样通过webpackresolve配置也可以达到通过包名直接引用移动部分的效果。2.是否可以不重复这个过程?1、困境融合开发第一版解决了开发者在项目维护、发布、用户包使用等过程中的精神疲惫问题,对PC端和移动端的逻辑复用有很大帮助。但是开发者在开发过程中还是有很多重复性的工作。比如虽然有完整的ts支持和接口声明,但是用户还是需要自己配置组件的setter。配置setter组件的过程主要是指定setter对应的属性、默认值和类型。例如,组件发布后,需要经过结算机制,才能在素材中心查看自己和他人的demo。比如在调试小程序的时候,每次在本地启动build的时候都需要打开小程序的IDE。这些都是每个业务组件开发中不得不做的事情,但是基本上是重复性的工作,所有重复性的事情根本就是有规律的,难道这些重复性的事情就不能做吗?2.自动生成prototype.tsx。如前所述,集成开发包中的PC和Mobile开发入口文件已经完全tsized和模板化。入口文件大致如下(这里是PC入口view.tsx,Mobile类似。):通过AST解析,我们可以定位到所有的接口声明和defaultProps声明。Typescriptlint只需要在一个文件中声明一个Class,加上Component的ts泛型类型,这些前置条件可以让我们定位到props的接口,从而得到每个prop的名称和类型。考虑到业务组件最重要的目的是能够在乐高中快速使用它们,我们不需要对每个类型和默认值做特别细粒度的映射。我们可以为基本类型找到对应的setter,对于一些复杂类型指定一个JSONSetter,render函数钩子的ActionSetter,回调事件的events。prototype.tsx的模板文件也是比较标准的写法,所以我们可以很方便的通过AST解析定义的属性,这些属性不需要再添加,插入新属性代码的位置,直接通过生成这部分Setter代码,我们的组件基本不用修改就可以在设计器中正常使用了(意思是可以配置各种属性,组件的各种功能可以流畅使用,而不仅仅是显示)。3.发布与自动同步。材料中心组件的发布只是第一步。只有能够发现一个业务组件,并且能够读取文档,才是组件服务的开始。在EnterpriseIntelligence中,我们目前使用MaterialCenter来统一展示组件。以前,业务组件只能通过素材中心的后台配置上传到素材中心。这个过程需要大量的人工填充,费时费力。我们也对这部分进行了优化。组件发布到tnpm后,vdev会收集上架的必要信息,比如组件拥有者、组件业务领域、组件适配结束等,素材中心直接提供API调用上传这些信息,同步到素材中心,实现一键发布+列表到素材中心的效果。当然,这种同步不是强制性的。对于某些测试版,您可以选择不同步。4、小程序WebIDE调试原来小程序调试必须在本地建立一个符合小程序结构的工程目录,然后使用小程序IDE打开相应目录开始调试。这个过程跨越了多个工具链,学习成本和运营成本都比较高。恰好支付宝小程序团队推出了@ali/mini工具链,可以根据项目目录启动Lyra浏览器模拟器进行调试。我们的集成开发包还集成了@ali/mini,为组件开发者自动生成@ali/mini所需的配置文件,可以直接启动WebIDE进行单命令调试。3.如何简单的开发/使用带有服务的组件?1.难点在上面两部分中,我们主要关注于一个纯UI业务组件的开发,但是我们也知道很多业务模块需要和后端服务一起使用才能完整的表达一个场景。最简单的例子是一个搜索器组件,没有服务,是一个带有特殊列表样式的选择组件。对于这类组件,过去有两种策略。一种是使用跨域的jsonp接口,但是随着现在安全形势越来越严,这样的接口越来越少了。另一种是匹配一个业务接口,但是这样的接口和组件联调很麻烦,因为接口只能在对应的业务域名下使用,因为这个限制,分离出两种不同的思路,一个是If你想在业务领域做一个页面或者干脆直接在业务项目中调整,更何况前端直接激活后端服务在本地调整。想想就很麻烦。新生可能只是搭建一个环境需要很长时间。另一种策略是在前端使用模拟接口或数据进行调试。这种环境比较简单,但是带来了很大的联调成本。首先,mock接口有时很难模拟线上的真实数据。二、谁来维护这个接口一直和线上保持一致,带来了额外的工作量。开发和使用不方便。由于接口属于业务本身,在本地或乐高启动调试时,无法调整接口,只能费力部署到业务页面,看看效果。或者在组件中选择默认不承载服务,然后在实际使用的时候再匹配对应的接口,就会出现使用组件找接口的情况。界面本身有多种形式,运行方式也不同。实际使用它需要一段时间才能看到效果。2、服务调用从上面的分析可以看出,这类组件的主要难点在于服务调用。没有跨域请求接口,本地开发困难重重。所以核心问题是提供一类可以在本地或者乐高环境下方便调用的服务,不用担心安全问题(数据泄露,服务商压力等),这就需要一个API网关,可以解决服务调用服务提供商的身份验证和保护。有了网关,接下来就是解决如何调用本地和乐高的问题了。乐高调用相对简单。乐高本身有后端服务。它只需要提供一个过程。当用户访问某个组件使用服务时,会去网关自动申请日常服务的调用。由于大部分日常业务已经脱敏并与真实数据隔离,无法直接用于生产,因此日常业务的订阅申请和审批相对简单。是的,这个过程可以直接在供应组件后面完成。拨打本地电话比较麻烦。本地调试一般都是从本地服务器开始(比如webpackdevserver等),很难直接完成后台接口的调用。这里有两种解决方案。一种是服务端提供了日常跨域调用的转发接口用于转发网关服务,比如/api/gateway?id=epaas.api.key,另一种是服务端提供了一个模板页面,前端服务器提供js和css注入到相应的页面中,这样就可以直接请求相应的接口了。3.实践在EI的实践中,恰好有这样一个业务网关ePaaS来承载网关的职责。在乐高的使用端,我们设计了一个业务能力模块来启用相应的组件和服务。ePaaS是通过应用间服务订阅来实现跨服务调用的,所以我们会让用户填写自己的ePaaS,然后再开通业务能力。其实乐高预览的时候不需要这些。让用户填写的目的是帮助用户一键完成自己的ePaaS界面。订阅,而不是要求用户去ePaaS去手动一一订阅。ePaaS的功能介绍当然,最终ePaaS网关并不是唯一的选择,我们也在积极拓展其他网关的接入。4、未来是什么?提高构建效率:上述的东西只是能,但还远谈不上好,尤其是频繁启动的调试命令,还有巨大的优化空间。每个人每次都节省10s,加起来就是很多时间。深入业务:目前在企业智能的部分业务领域已经铺开,但还没有完全覆盖。这套东西是从业务上来的,所以也应该回到业务上。业务的边界场景将带领我们逐步进入深水区。业务能力:能力是一个比较空洞的词。在我的理解中,它是一个业务功能为核心的无限数量的服务和UI(页面、块、组件)的集合。带有服务的业务组件是我们在这个领域的第一步是探索,接下来我们会继续深化,包括业务能力的乐高入门,业务能力的本地化生产等等。LowCode:乐高已经具备了低代码拖拽生成业务组件的能力,但只能用于低代码可视化设计器。理想情况下,应该可以在各种状态下流通,但是不管是业务相关的痛点,这个还在收集中。模型驱动?:这一点打上了问号,因为现在还只是一个idea阶段。目前页面已经实现了企业智能中ProCode、LowCode和模型驱动三驾马车的生产方式。业务组件已经有ProCode和LowCode两种模式,那么是否可以直接通过绑定模型来驱动UI,通过配置生成业务组件,在业务中复用呢?这在一定程度上也可以解决目前可应用于模型驱动的标准页面很少的问题。五、结束语以上是我们在业务组件开发中所做的一些小工作。核心方向是降低学习成本,减少重复性工作,简化复杂步骤。通过这些方法,我们可以改进前端业务组件的开发。影响。最后,欢迎加入企业智能-用户体验平台部前端团队。我们是阿里企业服务的先行者和创新基地。企业智能丰富于音视频会议、远程办公系统、大型ERP系统、企业运营、大型组织管理等方面。实践和业务场景。团队技术涉及可视化构建、跨端小程序、微前端、桌面端开发、模型驱动渲染、数据可视化、体验度量等前端方向,对这些感兴趣的朋友业务场景和技术方向欢迎联系我。作者:开发助手_LS原文链接本文为阿里云原创内容,未经允许不得转载
