波塞冬:伴鱼运营活动前端配置化实践

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"波塞冬,是伴鱼活动运营解决方案的总称,包含活动规则体系、h5 可视化开发平台等,名称来源于古希腊神话,波塞冬是海洋和所有水系的管理者,寓意为 palfish 发展提供超能力。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"目前的问题","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/06/06f2d8fa9529424c46040c5025933f2c.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"随着伴鱼业务的高速发展,大量促增长的活动接踵而来, 原有的研发模式暴漏出一系列问题,如后端逻辑混杂、复用度低、维护成本高,前端灵活性差、效率低,为了提升公司运营效率,我们急需探索一套符合公司现状的技术体系,为公司的业务高速发展提供平台支撑。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"万物终有源,要解决掉面临的问题,我们从整个研发、运营链路出发寻找答案。研发链路上在前后端分离的技术大背景下,我们的目标是要最大化的实现后端服务复用、前端页面复用,对运营而言是能够快速灵活的对活动策略、展示作出修改,来查验各种活动对业务的作用效果,基于以上思考,我们抽象了波塞冬平台的业务模型。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"平台概览","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bf/bf0a2b832dd5fe6626fc3c00f93fbb04.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"波塞冬平台主要分为三大部分:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基础服务规则:如消息通知、用户画像等服务。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"各种业务类型规则:例如拼团、签到、任务等类型的规则服务,在业务层面集成基础规则服务。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"h5 可视化管理平台:集成业务规则层逻辑,完成输出给 c 端用户。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为什么要这样分呢?我们结合现在运营场景进行简述。运营的呈现宣传方式以分为线下,线上两种方式,这里我们只谈线上。每一场运营活动都需要一些通用的服务,比如活动需要发送消息(微信、短信、站内信等),来增加活动的曝光,对于不同特征的用户我们希望展示不同的分流策略,这里有些用户特是不区别业务线的,比如用户基础信息(性别、年龄等);有些跟业务线强耦合,比如绘本的会员,少儿一对一的购买等,这些我们在应用层都统一成画像规则,最后由各业务画像规则引擎解析提供给下游消费,此类的基础能力我们统称为基础服务规则。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在基础服务之外还会有各种类型的活动,比如业务常用的任务玩法(录制绘本、去分享),签到玩法、拼团玩法等此类的玩法在服务层是可高度固化的,形式标准的 FaaS 服务(函数即服务),同样为了对运营友好使用,我们做成标准的业务规则模版,在业务规则层面通常会结合基础服务,比如一个拼团活动需要对新老客发送不同的奖励,对任务中的用户来发送通知提醒,督促用户来成活动。这样每一次的规则相互解耦,又可以灵活组合,从而达到服务高度复用,效率提升的目标。以上两层主要解决了服务端的复用。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对于 c 端我们应该如何复用?答案当然是组件化能力建设、可视化能力建设的范畴了,鉴于当前活动主推的运营场景是 h5 活动下面我们会重点介绍一下 h5 可视化平台的建设。以上就是对三大模块拆分的场景。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"h5 可视化开发的部分","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可视化开发一直是前端开发的热点话题,几乎所有大的公司都有自己的可视化配置平台,我们在建设可视化平台之前也做了充分的调研,下面以平台对比和总结的方式介绍。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"业界对比","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"h5 可视化平台的建设我们也调研了很多业界很多相关的资料,下面做了简单的汇总。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/23/2309bf113d302902a31058e2c551facb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"总结要点","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ff/ff357f5b96cd864ee2ced68bea9beca9.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过对业界的总结,我们需要寻找出符合公司技术现状的技技术方案。这里先描述一下 h5 活动开发的现状,现在每个业务线的 h5 活动都放在各自代码仓库,由于活动的性质(周期短,频次高)造成了了代码仓库的不断膨胀,且很多活动都是经过多次迭代,代码经手多人,代码逻辑不清晰,长时间会造成很多冗余代码,导致的结果就是维护成本上升,研发效率降低。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外活动的变更也是比较频繁的很多就是文字描述、背景图片等,这些改动不管是提测中,还是上线后都在发生,每次小的改动都需要走代码提交,发布的流程,且每次小的变更都需要全量发布,(比如多个活动同步进行,一些将要发布的代码已经合并到 master,而小的变更急需发布)产生一定项目风险。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基于上述的描述总结一下问题:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代码仓库庞大,长期代码冗余加剧,维护成本高,导致代码质量、研发效率降低。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对运营的支撑不灵活,小的发版对整体项目造成安全隐患。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此基于质量、效率、安全的纬度,我将 h5 可视化平台划分为三个模块","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"组件开发脚手架:我们提供了脚手架让开发高效、规范化的进行组的开发与发布","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可视化编辑器:提供将组件拼装成页面的能力。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理后台:人员、组件、页面等纬度的权限与版本管理能力。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"组件开发","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"该模块我们要从代码源头把握研发的质量与效率,因此脚手架提供了统一的组件开发模版,且每个组件在发布时候都需要关联到 git 源代码管理的仓库,这样就将原有庞大的代码仓库,以研发组件纬度进行了仓库解耦,到这里你可能会有疑问,解耦之后我的通用模块如何调用?比如桥功能,接口调用,这里我们结合 webpack 的生态能力,在研发模式下,我们将通用能力的以 externals 的形式在组件中调用,同时在打包发布阶段只发布组件本身的内容,从而减少了组件代码体积。当然影响研发效率的问题还有很多,比如 h5 开发通常用到桥的能力,本地预览的能力,属性编辑的能力等这里我们都研发对应的模拟桥工具,动态表单,iframe 等模式来解决上面的问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了去研发模式的思考,基于业务我们也将组件进行了划分,方便对业务进行有力的支撑,以下是我们的组件模块划分。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"业务组件:顾名思义就是我们之前整理好各种常用业务规则所开发的组件,为特定业务所服务,比如我在业务规则 服务划分的时候有拼团、签到等服务模块,对应的展示层我们一些通用的组件方便类似业务的直接使用。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基础组件:基础组件是我们常用的基本 ui 组件,比如按钮,文本、图片等,达到基础的视图要求。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能组件(待讨论):这个是我们比较特殊的一个组件类型,业务组件与基础组件都有一些通用的行为,比如我点击按钮弹出桥分享的能力以及对组件统计曝光的能力,此类的组件没有 ui 的作用,仅提为组件注入通用的交互行为。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面以图文的形式大家作下展示","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9a/9aa47800b64a588e9ec1e6175b9d2854.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这是我们组件开发的界面,为了可以更好的给开发者提供开发环境,我们集成了编辑器的所有功能,从而保证展示效果是一致的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"组件作为整个波塞冬重要的部分,在设计的时候我们考虑集成了以下大功能:","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"配置数据","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对页面的可编辑部分, 需要准确描述可编辑部分所需的配置数据; 配置数据是异构的, 不同页面、不同区块的配置数据各不相同。所以需要对不同页面、不同区块定义各自配置数据的数据结构和字段类型。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最理想的配置数据格式为 JSON, 因为其格式灵活, 前端友好; 最理想的配置数据描述是 JSON Schema, 因为其支持表单动态生成和数据校验。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"组件交互","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面我们有讲到,将所有的组件代码解耦分布在不同的仓库,看下图描述的场景。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9d/9d0d80b08fa61735d98d7fbeedb0d845.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们最终要解决的是不同组件的通信问题,跨组件通信大家都不陌生,比如EventBus等,结合到业务我们需要解决将组件的内部的方法暴露给其他组件,并且在指定的绑定事件(点击、焦点等)中触发方法。在实践中划分两部分解决这个问题:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)组件开发阶段,在组件描述的中定义方法名字,比如我们约定描述属性名称为editorMethods,需要对外暴露的方法为goShare,这样组件就对外提供了方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)组件编辑阶段,编辑器内部维护了一个存放当前组件中所有对外方法的数组,以及可以交互的事件,当选中具体组件的时候,可以指定绑定组件的事件方法。下图为在编辑器中的使用展示。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c0/c0ed084de947d57cd6f658feec4aa930.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"数据总线","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"数据总线主要解决了组件之间数据共享问题。同样结合下面图的场景理解,后端接口的数据多个组件都会使用到,每个组件中都调用一次接口会造成性能问题。vuex可以很好的解决这个问题,在编辑器内部定义约定Store的对象,不同的接口数据设置不同的Store对象属性,既可实现数据共享的能力。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/93/939cb71c9b4632da7a04572166c262bf.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"页面模板","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"模板是带有默认数据的页面; 对于组件化的页面, 模板是从组件库中选取部分组件, 并带有各个组件的默认数据。采用模板生成页面, 只需对模板进行少量编辑即可实现页面快速生成,比如项目中沉淀了许多海报模版,,素材库模版,直播模版等","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"页面编辑器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原有的方式中都是一个代码仓库中代码形式的组件复用,编辑器让组件的复用也可视化的方式,简单的页面组装让非研发同学也可以做页面。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b2/b26ed193343dcf5dbb7de82e91db8f3b.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这是我们波塞冬编辑器的编辑页面,总共五个部分。顶部主要是我们的页面设置部分,提供了页面的保存发布预览等功能。下部分从左往右依次是:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"组件列表:这里展示我们通过组件工具发布的所有组件。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"页面组件树:页面组件树是页面的骨架,由内置的各个组件组成。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"展示编辑区域:这里主要是进行组件的位置操作,拖拽组件的位置,进行页面编辑。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"属性模块:因为每个组件都有可配置的属性,这里主要是根据选中的组件进行配置,比如按钮组件的颜色大小等,取决于这个组件有什么属性。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"管理后台","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理后台是整个可视化的控制枢纽,重点在于对业务场景应用的管控。做为一个平台组件可以随心所欲的发布,但不可发布的组件并不能都生效,因此平台要对发布组件做质量检查,通过过审核后才能在可视化编辑区使用;同样页面可以随意的创建,但是不能让别人轻易动我创建的页面,比如 a 业务的同学,编辑并发布了 b 业务的页面,因此在页面上层我们划分了项目团队的概念,只有项目中的成员可以修改归属于项目的页面。现在我们发布页面方便了,原有代码部署的方式发现错误我们可以快速回滚,这里我们同样提供了页面回滚的能力,每次的编辑器内发布的内容都会有一条 content 内容发布记录,方便回滚历史提交,以上就是对后台的介绍。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"展望","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前波塞冬平台体系还处于建设的初级阶段,可视化部分承载了目前业务内的所有海报生成工作以及部分活动页面,在互联网已经进入下半场舆论下,用户运营已经成为各大公司的重中之重,能够对用户做到精细化的运营,对公司成本、效率越来越重要,做为技术人员我们以技术驱动产生平台,用平台支撑业务发展,从而使公司变得更大更强,未来我们期待波塞冬体系能够成为建设完成,成为真正的海神。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"参考文献","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://juejin.im/post/6844903608614387720","title":null},"content":[{"type":"text","text":"页面可视化搭建工具前生今世","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tech.meituan.com/2017/03/09/waimai-lego.html","title":null},"content":[{"type":"text","text":"美团乐高","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://godspen.ymm56.com/","title":null},"content":[{"type":"text","text":"godspen","attrs":{}}]}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章