找回密码
 会员注册
查看: 22|回复: 0

字节跳动二次生成能力加持下的UI智能生成实践

[复制链接]

2万

主题

0

回帖

7万

积分

超级版主

积分
73800
发表于 2024-10-1 03:02:14 | 显示全部楼层 |阅读模式
作者|朱睿力 编辑|贾亚宁 本文由 InfoQ 整理自字节跳动前端工程师朱睿力在 GMTC 全球大前端技术大会(深圳站)2021 的演讲《二次生成能力加持下的 UI 智能生成实践》。随着业务量的增长,用于支持业务的轻量 H5 页面的开发逐渐成为一个耗费大量时间和人力的棘手问题。这些业务开发繁琐,难以沉淀,缺少自动化,如何提高这类 H5 页面的开发效率越来越成为业务增长过程中的一个痛点。UI 智能生成代码也成为解决这个问题的探索方向之一。本篇文章会主要介绍字节跳动抖音前端团队所探索的智能生成代码项目 ALYX 的解决方案、ALYX 和我们的搭建平台(魔方)的配合以及二次生成能力如何助我们生成复用度更高的页面。ALYX本文会先从业务场景出发,在讲解我们的主题【二次生成能力】之前,先带大家过一遍在没有二次生成能力的时候,我们曾经的单次生成模式流程,然后一起看看它有什么问题,以及为什么我们后面需要二次生成能力去解决这些问题。 背景 业务场景介绍 在谈论解决方案之前,当然要先明确业务场景。我们的业务场景主要是抖音活动。抖音活动如下图所示,基本上都是一些移动端的 H5 页面。这些页面的一个显著特点是上限会非常的高,同时下限也会非常的低。抖音活动示例下限如一些静态的页面,没有动态的内容或效果,在结构和布局上也非常简单;上限如有些页面会有一些比较复杂的组件和玩法,像任务、抽奖、用户列表等等较为复杂的模块。这些页面足够简单,以至于对研发来说,开发它们是一种非常繁琐、没有积累且缺少意义的工作;它们又足够复杂,复杂到刚好处于“难以完全自动化生成”的一个临界点。这类业务问题非常难以解决,导致我们处于一个非常尴尬的境地。 魔方低代码搭建平台 为了解决这个业务难题,我们团队内部诞生了魔方低代码搭建平台。像其他的低代码平台一样,它的目标用户是我们的运营同学,希望赋予运营同学通过拖拽组件的方式搭建起一个活动页面的能力,从而来缓解研发的一些重复工作。魔方也很好地回应了我们的期待:魔方平台经过 4 年的平台建设,现在已发展为字节系全产品的活动平台,每月稳定支持上千个活动高效上线,活动流量高达数亿。然而魔方并不是一个完美的解决方案,发展到后来也出现了新的问题。魔方低代码搭建平台随着业务复杂性的提升,我们会发现魔方变得越来越复杂、学习成本越来越高了。为了支撑业务的复杂性,搭建平台本身的复杂性也难以避免地随之提升。这就违背了我们一开始的初衷:为运营提供一个易于使用的、无需研发参与的页面搭建平台。 ALYX 的诞生 在遇到这个问题之后,我们团队内就开始有了 ALYX 项目的想法。ALYX 是一个前端智能化的项目,或者简单来说是一个设计稿转代码项目。我们希望通过 ALYX 的智能算法来帮助运营,从设计稿直接自动生成他们想要的一个页面,帮助运营减少搭建这一部分的工作,从而跳过一些魔方复杂的搭建操作,进而减轻魔方的复杂度问题。ALYX 的诞生ALYX 诞生的初衷就是减少业务中重复繁琐低复用的劳动,提高业务的整体开发效率。到目前为止 ALYX 已经取得了一些阶段性的成果,现在已经支持了 Photoshop 和 Figma 等多种内部常用的设计软件,也支持了多种的导出产物,如代码、魔方平台的活动以及魔方平台的模板。简单透露几个数字:现在 ALYX 已经支持了内部 100% 的魔方模板生成,为我们的模板制作这个场景带来了超过 60~70% 的效率提升。ALYX 用这些数字证明了自己的价值,那么我们是怎么做到的呢? 单次生成模式的实践 我们先来聊聊单次生成模式下我们团队的一些实践。在介绍一些复杂模块之前,首先让我们简单过一下 ALYX 的一个简化 Pipeline。需要强调的是,下图所示只是 ALYX 的一个最简化的 Pipeline,它只保留了一些最必要的项目,实际的 Pipeline 会比它复杂得非常多。ALYX 简化版 Pipeline首先我们需要一张(或多张)设计稿,接着是结构重组。为什么要进行结构重组呢?我们拿到的设计稿是由设计师所生产的,而设计师所关注的主要是设计图在视觉效果上的一致性,并非其在结构上的合理性,但是页面结构恰恰是对于研发来说非常重要的。所以很有可能你拿到的看上去一切正常的设计稿,实际上图层结构却和对应的实现代码结构大相径庭,这样的话研发后续要在上面去做一些修改或者二次开发就会非常困难。所以我们宁愿完全抛弃掉设计稿原有的结构信息,只保留图层本身的信息以及图层之间的相对高度信息(用前端的话来说就是 z-index),然后由我们自己的算法去对所有的图层进行重组,重组出我们自己认为一份既可以有效保留设计稿信息,又具有相对可读性与二次调整能力的结构,这就是结构重组需要做的事情。结构重组之后我们需要对循环进行处理。我相信循环是前端代码开发 H5 页面的过程中非常重要和常见的部分,这一块我们后面会去更加详细地讲一讲。结构重组和循环处理这两部分我们称为布局部分。布局完成之后,我们会进行一个生成的步骤。生成的第一步是对样式的生成,因为设计稿中所带的样式信息是和 CSS 的格式完全不同的,是不能被浏览器直接理解的,因此我们要通过样式生成这个步骤,来把设计稿中的样式信息去转换成浏览器可以理解的 CSS 样式代码信息,这就是样式生成。样式生成之后接下来是组件转换。组件和循环一样也是一个可以复用的页面中必不可少的部分,后续我们也会去详细介绍。生成部分完成之后,我们就可以通过不同的 DSL 生成不同平台的目标了。比如说通过 React DSL 就可以将我们的 Schema 转换为 React 代码;如果生成目标是魔方的活动页或者模板,我可以用另一个魔方的 DSL 去生成最终的结果。 循环处理 在上面的流程中,我们开发过程中遇到的第一个问题就是循环。什么是循环?为什么需要循环处理?让我们看看下图中的例子。有循环处理和无循环处理的对比如果我们要去生成图中这么一个列表组件,我们希望它生成的代码是什么样子的?先假设我们上面的流程中没有循环处理,大家可以想象一下我们会生成什么样的代码。假设没有循环处理这个步骤,那么列表的每一项之间是毫无关联的,那么按照上述的步骤流程,算法会把列表的每一项单独拿出来生成一遍。也就是说列表的三项是完全独立生成出来的,它所有的数据也都是静态且毫无关联的。这样的一个生成结果就很难去复用或者说二次开发,就算只是更改数据也会非常困难。我们希望能生成 React 中循环的代码形式:将 state 中的一个数据数组,通过 map 方法,得到一个新的 JSX 数组。这种代码中所有的数据都是动态的,如果要去修改数据或者二次开发,只需要修改 state 中的数据数组就可以了,这是我们理想的一个状态。除此之外,我们可以预见这种代码在代码量上也会有一个精简。图中的例子如果没有循环处理,它生成的渲染函数是 50 行,相比之下加入循环处理后是 30 行,CSS 代码也从 345 行精简到 270 行,这也是非常可观的精简。实际上我们这个例子中的列表比较复杂,每一项之间差别很大,如果是那种更加规范的列表,项与项之间差别比较小的话,精简的数字会更加可观。相信在给了这个例子之后,大家都会认可循环处理肯定是我们生成可复用代码的一个必不可少的环节。那么要怎么去实现它呢?这里我会一步一步地给大家讲解我们的实现方案。 循环节点间的匹配 让我们从最基础的开始:我们需要知道两个节点是否属于同一个循环。通过循环节点间的匹配算法,我们可以解决这个问题。以下图一个用户列表组件为例:对图中列表的两项,我们做的第一件事是把这两项分出来放进两个沙盒之中。沙盒的作用是消除它们的位置以及外部的节点对于它们本身的影响。用户列表组件放进沙盒中之后,我们可以把每一项的子节点树做铺平处理,把所需要的关键节点铺平开来,之后对所有的节点两两之间计算一个相似度。相似度可以通过它们的大小、类型、位置等等一系列的信息去计算。得到两两之间的相似度之后,我们可以通过 Hungarian 算法在二者的元素间做一个分配,得到一个最佳的两两匹配列表。比如说在这个例子中,两项的头像和头像间可以做一个匹配,用户名和用户名可以做一个匹配,关注按钮背景可以做一个匹配。如果你比较细心,会发现下面一项其实有一个直播标签没有匹配到上面的任何一个节点,这也是没有关系的,我们后面会去处理它。 区间内寻找最佳循环 现在我们知道怎么去确定两个节点属于同一个循环,那么就可以开始去寻找整个循环了。我们这里做的是一个偏暴力搜索的方式,首先对结构树做一个前序遍历,在遍历出来的节点列表上找一个区间,然后在区间里面去搜索循环。如下图中这个例子:假设我们在 1~7 这个区间内去搜索循环,我们会发现当步数为 2 的时候,抽出来的子节点树按照我们上述的方法,它们两两之间实际上都是属于同一个循环的,因此我们可以确认的是这三个节点一起构成了一个循环。这就是我们寻找整个循环的方法。这个方法比较暴力,那么它的效率会不会非常低呢?实际上我们会运用提前退出、动态规划等方法来提高它的效率,在实际测试中它的计算效率其实是非常可以接受的。搜索循环 循环合并 我们现在是不是就可以找到我们想要的循环了?其实还缺少一步。你可能也注意到了,我们的上一步有一个非常致命的缺陷,即它过于依赖元素在结构树中的前序遍历顺序。这又会有什么问题呢?我们看下面这个例子:对于图中的一个明显的循环结构,假设它在结构树前序遍历的顺序是先是上面三个图形,然后才是下面三个对应的名字(即顺序是:方形,圆形,三角,Rectangle,Circle,Triangle)。那么按照我们上述的寻找循环方法,我们是不是会找出来两个循环?即前面三个图形作为一个循环,后面三个文字作为另一个循环。这肯定不是我们想要的,我们想要消除我们的算法对于结构树前置遍历顺序的依赖。循环合并因此我们会做一个循环合并,对相邻的循环,根据他们的对齐关系、列表长度、元素类别等等多种信息,去尝试把它们合并起来,得到我们想要的最佳循环,以此来消除我们的方法对结构数上顺序的依赖,这就是循环合并所做的事情。 提取循环项 很好,现在终于可以找到我们想要的循环了,那么我们是不是就可以直接生成最终的循环代码了呢?很可惜,没有这么简单。因为我们只是相当于给我们认为是循环的节点树打上了一个标记,知道了这些结构树节它是一个循环,然而这并不能非常神奇地直接转换成我们想要的 React 中的循环代码。让我们回忆一下我们想要的 React 中循环代码是什么样子的:一个数据数组通过 map 方法转变成一个新的 JSX 数组,然后交给 React 去渲染。关键就在于 map 方法,那么 map 究竟做了什么?map 是将一个统一的结构重复很多遍,在每一遍重复的时候可能会去做一些变化,由此来形成一个新的数组。这里面有两个关键词,一个是『统一的结构』,一个是『变化』。要生成我们想要的代码,就得先解决这两个关键词。我们先来看第一个关键词『统一的结构』。我们需要对我们的循环去定义它的统一结构,然后去尝试提取出这样一个循环的统一表现形式。在提取这个统一结构之前,我们当然得知道我们接下来要提取的结构是什么样子的,因此我们需要先来设计一下这个所谓的统一结构。那么这里就有一个问题,这个统一结构,它应该是列表每一项信息的一个并集(我们称之为『最大集』),还是每一项信息的一个交集(我们叫『最小集』)呢?统一结构到底指的是什么假设我们想精简一下我们的统一结构,选择最小集。我们看下图的例子:图中的用户列表中,大部分项会有一个直播标签,小部分没有。如果我们选择最小集,也就是列表项信息交集的情况,我们会得到左边这么一个统一结构,是不包含直播标签的。最小集:What if....那么我们在后面去重复 + 变化这个结构的时候,每当需要这个直播标签的时候,我们都需要去添加这么一个直播标签元素。这些直播标签实际上都是一样的,但由于它们不在统一结构内,我们每次都需要去添加一个新的、重复的元素。这其实带来了一个冗余数据的问题。也就是说尽管我们想要整个统一结构更加精简,最后的结果却和我们一开始的预想背道而驰,这并不是我们想要的。所以我们其实最后选择了『最大集』的方式,也就是将列表每一项的信息做一个并集。下图还是一个用户列表的例子,不过更加复杂一点。在我们提取它的一个最大集之后,会得到图左所示的结构。你会发现一个很神奇的事情:那就是左边的这个结构不出现在实际的列表之中,因为它是整个列表的一个统一的表现形式,而不是某一具体的项。或者说它是一个列表多种状态归一的一个聚合体。最大集好的,现在我们已经解决了第一个关键词“统一结构”,让我们来看第二个关键词“变化”。变化就是统一结构在重复过程中可能需要根据数据或 index 的值做一些修改。那么我们是不是只需要把统一结构和我们实际的循环的每一项一一对比,然后去提取这个变化的地方就好了。原理确实是这样,但是实际去做的时候我们会发现,由于设计稿中的列表实际上不是一个真正的循环,它的每一项可能都是单独绘制的,那么项与项之间的结构差异就可能会非常大。如果你强行把这样的结构和我们设计好的统一结构去对比,很有可能会发现你提取出来的变化量太大了,生成的代码也是不可用的。所以在这之前我们会做一步优化,就是从循环项去重新生成整个循环:我们把设计好的统一结构去重复,然后去修改它,使得新生成的循环和原来的循环在视觉上是一模一样的,但是它的结构都是从我们的统一结构变化而来的,这样一来新的循环的每一项的结构都统一了。在这之后我们再去做提取“变化”的时候是不是就更加方便了?从循环项重新生成循环在做完这一步优化之后,我们就可以很方便去将统一结构和真实列表一一对比,从而提取循环值了。提取循环值我们解决“统一结构”和“变化”这两个关键词之后,其实距离生成我们最终想要的循环代码只有一步之遥了,这里就不做赘述了。 组件处理 在解决循环问题之后,我们很快就会遇到另一个问题,那就是逻辑的生成。我相信很多 D2C 开发者都和我们一样,不只满足于页面 UI 和结构的生成,很难不尝试涉足逻辑生成的领域。即除了高保真地还原页面 UI 与结构,也希望能够同时还原出业务逻辑,达到真正的“零代码”。可是理论上设计稿中是不包含任何与逻辑相关联的信息的,我们要从哪里去生成这些逻辑的信息呢?让我们回到我们的业务场景。为了减少运营的理解成本,魔方低代码平台中运用了大量的业务组件,业务组件就是一种将一个业务相关联的逻辑全都包揽起来的非常复杂的大组件,这种组件对于运营来说,其内部就是一个黑盒,用户不需要去关心,只需要负责填充数据就好了。在这种业务场景下,我们会发现我们绝大部分的逻辑都已经被封装在这些复杂的业务组件之中,从而赋予整个页面的。也就是说业务组件能够完成自闭环,几乎不需要再额外增加代码。那么是不是我们只要能生成这些业务组件,我们就能附带地生成这些逻辑?因此在我们这种特定的业务场景之下,逻辑生成约等于组件转换。 组件识别 在做组件转换之前我们肯定需要先知道哪些节点是什么组件,这也就需要组件识别能力了。这里我们采用了深度学习的方法,模型是 YOLOv5。YOLOv5 是一个对象检测模型,所谓对象检测就是给模型一张图片,它可以在图片中找到你想要的标签以及标签的大小和位置,如下图所示帮你框选出来。这个模型就非常适合我们对组件识别的需求。我们是基于一个预训练好的模型,再用我们的数据去 fine-tune 的,到目前为止已经可以识别按钮、选项卡、抽奖、视频等等很多简单和复杂的组件了。YOLOv5 对象检测模型同时我们支持子语义识别,比如模型可以区分普通按钮、提交按钮和返回按钮等等。这里不会详细去讲我们的模型,其他文章中已经或多或少涉及到了。但是需要注意的一点是,我们在实践中发现了一件非常重要的事,那就是数据比模型其实更加重要。很简单的道理,因为你的数据其实决定了你的模型的上限。我们在数据上花的时间实际上比在模型上多很多,也在这方面做了很多工作,比如说数据的整理、标签的平衡、脏数据的筛选、页面分割等等。这里举个页面分割的例子:YOLO 模型的输入大小是固定的,比方说我们假设它的输入是一个 256×256 的正方形尺寸。那么这时候如果把一个非常长的页面给喂进去尺寸是不搭配的,所以只能对输入的图片做一个拉伸畸变,也就是将其强行转成 256x256 的大小。随着畸变造成的就是信息的压缩,也就是原本数据信息的丢失,进而导致模型的效果变差,这是不可接受的。下图是一个简化的例子,实际的页面会更长,如果不做处理导致的畸变会更大。图形的拉伸畸变所以在将图片数据喂给模型之前,我们会先将页面进行分割:即在不中断页面中某个组件的情况下,将一个页面切割为多段的小页面,然后分批地给予到我们的模型,最后再将识别结果重新组合起来。这样的话就可以减少页面的畸变以及数据信息的丢失,以此来提升样本的精确度。 组件转换 组件识别完成之后,我们是不是就完成了组件的工作呢?其实和之前的循环一样,答案是还没有。我们相当于只是给元素标注了它可能是什么组件,并不能直接把它转成代码。因此需要组件转换这一步来把它转换成真正可用的代码。第一种转换方式,也是非常符合直觉的方式,就是基础转换。基础转换就是为每一个组件去定制一个它独有的转换函数,转换函数的作用是将我们从设计稿导出的 Schema 输入进去,输出对应组件所需要的 props 和 styles 的信息。这是一种非常简单非常符合直觉的方式,然而它显然是不够的。为每一个组件自定义一个转换函数在基础转换之后,我们又开发出了一种新的转换方式叫做深度转换。相比于基础转换,深度转换其实走到了另一个极端。深度转换在运行时转换,将 React 的虚拟 DOM 树和我们从设计稿中导出的 Schema 进行匹配,给 Schema 的节点绑定其匹配上的虚拟 DOM 节点上的属性和事件,然后将绑定好属性和事件的 Schema 转换为一个新的虚拟 DOM 树交给 React 去渲染。简单来说它的原理就是我们在运行时拦截了原有组件代码的渲染函数,并进行了替换。如下面所示,图中是一个我们原先开发好了的 Button 组件,该组件本身会渲染出一个 VDOM,深度转换拦截了它所渲染的 VDOM,从 Schema 重新生成了一个 VDOM 并替换了原先的 VDOM,再交给 React 去渲染。深度转换让我们举个例子,下图中依旧是一个用户信息组件。如果我们从该组件的设计稿导出 Schema,得到结构可能如左边所示一样的一个结构树;而原先开发的该组件的代码,它渲染出来的 VDOM 结构可能是右边这样。可以看到他们两者之间其实会有很多不一样的地方,但是没有关系,我们会通过一个匹配算法,把二者的关键节点之间去尝试做一个匹配。下图的匹配结果是:左侧的头像图片匹配上了右侧的 img.avatar 标签,左侧的用户名文字匹配上了右侧的 p.username 标签,左侧的关注按钮图片匹配上了右侧的 div.follow 及 p.follow 两个标签等等。(举例)用户列表深度转换匹配完成之后,我们就可以把右侧标签上绑定的事件和属性去绑到左侧它对应的元素身上,这样就形成一个新的带有属性和事件的 Schema 结构,我们再把新的 Schema 结构转换成 React 支持的 VDOM,之后交还给 React 去重新渲染,就这样完成了一个狸猫换太子,替换渲染函数的工作。我们还发现左侧有一个分数的文本,它实际上没有匹配到任何标签,这可能是因为我们原先去开发这个组件的时候并没有考虑到这种使用场景,所以显示用户分数这个功能是原有组件不支持的。但是也无妨,我们这么匹配之后,就完全可以把这个没匹配上的元素转换为一个支持编辑的常量,它也会被正常的渲染出来,并可以在魔方编辑器中被手动编辑。基础转换和深度转换这两种组件转换方式实际上不是一个替代关系,而是一种相辅相成的关系。基础转换的优点很明显,它是人工适配的,所以它的转换率会非常高;但是它的缺点也同样明显,那就是它消耗人力难以维护。这很容易理解,因为我们既然是根据组件来写的转换函数,那么每次我们组件有更新,它相应的转换函数也需要一起更新,这就是一个非常繁琐的过程。因此基础转换比较适用于一些简单的组件,如 Button,video 之类可以直接替换背景的组件,或者是功能和 DOM 结构不相关联的组件。至于深度转换。它的优点就是另一个极端:它无需任何的适配和维护就能适用于大部分场景,开箱即用,甚至可以实现原组件无法实现的样式。比如说我原先开发了一个用户列表组件,开发时只支持竖排,但是经过深度转换的替换工作之后,它实际上也可以去支持一个横排的效果了。当然,它的缺点也非常明显:它是一个自动的匹配算法,这就意味着算法可能会失败,所以它的转换率会低一点;并且因为它替换了 VDOM,所以它无法作用于功能和 DOM 结构相关联的组件,这种组件就只能交给我们的基础转换了。它适用于基础组件集合体类组件,比如用户列表就是用户头像、用户名、关注按钮等一系列这种比较基础的组件,通过内部的一套逻辑相关联起来的一个组合类的组件,这种组件就非常适合我们的深度转换方式。至此,我们完成了循环和组件,我们在优化生产结果上实际上已经做了非常多的工作,可是这样对我们来说就够了吗?我们现在单次生成的流程在实践中遇到了一个困境。让我们看看下面的流程图:当我把设计稿交给算法的时候,算法会直接帮忙生成一个最终的结果,可能是代码或者是魔方的页面,在这个基础上我们可能会去做一些人工调整,如填充数据、调整层级等。单次生成的困境在这之后,如果我们发现之前的转换出现错误, 比方说某组件识别错了,该怎么办?在现在流程下我们其实是没有办法很好地去解决这个问题的,我们只能让它重新去生成一遍。可是如果重新生成,那么我们就会丢失之前所有的人工调整,这对用户来说会带来一个很大的阻力,通俗来讲会觉得我们这个产品非常不好用。所以我们其实经常听到对我们 D2C 开发者而言非常刺耳的一句话:生成的还不如重新写的。一个很残酷的现实是:为了让生成的代码贴近用户的使用习惯,每 1% 的进步都会消耗开发者大量的时间和精力。尽管如此,即使能生成 99% 符合用户需求和习惯的代码,那最后的 1% 都是到达“好用”前难以逾越的巨大鸿沟。 二次生产能力加持下的智能布局 人工还是智能? 为了解决上述的问题,我们开始尝试探索二次生成能力。在此之前,让我们从一个很简单的问题开始:人工还是智能?这里我问大家一个问题,人工智能是一个黑盒,如果生产环境出现问题,我们要如何去追溯?我们认为这个是很难的,所以我们第一点思考就是:纯智能解决一切在目前为止还是不太现实,我们很难避免人工的介入,需要用人工来为机器兜底。基于这一点我们有第二点思考:既然人工的介入无可避免,那么我们需要的可能并不是一个单纯人工智能平台,而是一个人工与机器相配合的平台。 二次生成能力的探索和实践 基于这两点思考,我们开始探索理想中的一个新的二次生成能力加持下的流程。二次生成能力的探索和实践在这个流程中我们将设计稿交给算法之后,算法并不是直接生成一个最终的结果,而是生成一个中间的表示形式。在这个中间的表示形式上,我们已经可以去做一些人工调整了。同样的如果在人工调整之后,我们发现错误,就可以把中间表示形式重新交还给算法,算法可以在纠正那些错误之后,并且在保留之前的人工调整的同时,去生成一个新的中间表示形式,这就是一个中间表示形式的良性自循环。在我们解决完问题,所有都一切无误的时候,才会去生成最终的产出。这是一个比较理想的新流程,在这个流程中人工其实是在给机器纠错,机器会在原有的基础上去重新生成,我们不再需要从头重新来过了。在新的流程中,人工从一个生产者的角色,变成了一个检查者的角色,这实际上是一个质的变化。 实现:中间页和重布局算法 为了实现我们理想中的这么一个中间表示形态自循环,我们开发了中间页和重布局算法,中间页是搭载这么一个自循环的平台,重布局算法就是实现自循环的一个核心算法。在中间页上我们可以做很多的人工调整工作,包括对识别错误的组件进行修正、对循环的修正、手动调整层级结构、标记固定和移动布局等等。在加入中间页之后,我们在从设计稿直接到产出这个流程的中间添加了一步,即先到中间页再到最后的产出。那么这一步会不会对我们的用户会带来新的复杂度呢?我们认为其实并没有,因为在实际的生产中,设计稿的部分和后续的产出部分实际上是由不同的角色来负责的。设计稿这边由设计师来负责,对设计师来说,增加的工作只有安装我们提供的插件,然后就可以一键导出,也不需要去做任何的规范;反而,ALYX 为他们减少了切图以及大量的沟通工作。对运营来说,虽然在产出之前多了中间页的步骤,但是中间页实际上帮他完成了手动搭建页面的工作,也提升了他们的效率。因此我们认为中间页的加入实际上并不会给我们的用户带来新的复杂度。重布局算法可以看到,新的流程下关键的核心部分,也就是 Schema 到 Schema 的这个部分,就是实现中间形态自循环的一个核心算法,我们叫重布局算法。很有意思的一件事情,我们虽然是在做 D2C,即 Design to Code、设计稿转代码,但是现在新的流程下,我们的核心步骤已经不包含 D (Design) 也不包含 C (Code) 了,因此我们给这个核心部分取了另一个名字:智能布局能力。 二次生成能力加持下的流程 让我们回顾一下二次生产能力加持下的一个新流程:首先是初始化的步骤,在初始化过程中我们会用布局算法对设计稿做一个最小化整理,这里也会去做组件的智能识别;之后用户在中间页可以去做一些人工的修改和调整,如通过打标的方式去修改组件、调整分组等;人工调整的同时会调用智能布局的能力去保证最后生成页面视觉上和结构上都是合理一致的,最后导出目标平台的产物。二次生成能力加持下的流程 2-1或者我们换一种更容易理解的说法:首先让机器去帮我们做出推荐;在这个基础上人工只需要去做出一些调整的命令,机器来完成这些调整命令,并且保证最后的页面视觉结构是合理的,即是智能布局;最后导出结果。二次生成能力加持下的流程 2-2 总结 ALYX 智能算法在魔方低代码搭建平台之上,为用户提供了简单搭建起一个 H5 页面的解决方案,帮助用户跨越从设计稿到最终页面间的巨大沟壑。相信在不久的未来,魔方和 ALYX 会成长为更加成熟、更加智能的低代码解决方案。 作者简介 朱睿力:字节跳动 抖音前端工程师。魔方 ALYX 项目的设计者和核心开发者。2014 年接触前端开发,自 CMU 毕业后 2020 年加入字节跳动,从 0 到 1 搭建起 ALYX: UI 智能生成代码项目的架构和算法体系,期间负责核心布局算法的开发,React DSL 的优化,深度组件转换算法的研发,中间页的架构和开发等工作;目前仍然是 ALYX 项目的核心维护者及开发者,对前端架构、前端智能化等有着深刻的理解。 活动推荐 2022 年 6 月 10-11 日,GMTC 北京站与您再度相约!点击底部【阅读全文】直达大会官网,更多精彩内容持续打磨中。大会门票 7 折限时优惠,立减 1440 元!千万别错过!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-13 17:13 , Processed in 2.143280 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表