猫耳大型活动提效——组件低代码化

news2025/3/12 0:12:55

1. 引言

猫耳前端在开发活动的过程中,经历过传统的 pro code 阶段,即活动页面完全由前端开发编码实现,直到 2020 年接入公司内部的低代码活动平台,满足了大部分日常活动的需求,运营可自主配置活动并上线,释放了相当一部分的开发人力。不过,此时的方案仍然无法很好地服务大型直播活动场景,比如年度 S 级的直播活动,这类活动赛程多且持续时间长(可长达两周),页面和组件都包含多种状态,运营难以配置出大型直播活动的所有需求,故此阶段的大型活动仍然完全由开发编码实现,需要占用较多人力,但此类活动从数量上来看连 1% 都不到。鉴于我们已在日常活动中积累维护了相当多功能的低代码组件,如何复用已有的低代码组件来更快实现更多活动玩法就成了一个值得研究的问题。此外,大型活动从筹备到结束,时间长达数月,而密集开发阶段可能只占其中的一个月,密集开发结束后的长尾需求又该如何优化提效?接下来本文将介绍猫耳前端在活动场景的低代码探索经验,以及最终稳定的开发模式。

2. 场景分析与问题识别

2.1 不同场景的开发方案

把时间先拨回 2022 年,当时我们已有一定的平台使用经验,从技术角度将活动划分为两大类型,根据业务需求采取不同的方案:

2.1.1 配置类页面(Low Code + No Code)

此类活动经产运及技术负责人评估后,若无需开发参与则由产运同事自助配置并上线。若需要开发参与,则视情况修改组件或开发 JS 或 CSS 补丁代码来实现,沉淀下来的代码也可用于后续的类似活动。

图片

2.1.2 开发类页面(Pro Code)

图片

在一些玩法较为复杂、活动状态多的场景,配置页面的难度可能会呈指数级上升,当时平台也并不具备完善的预览能力,所以此类活动几乎完全由开发负责实现(部分页面可能会跳转到配置类页面)。虽然工作量较大,但简单来说就是根据设计稿、产品需求文档、接口文档这几个关键输入来实现活动页面,在流程上并没有太多可说的。

图片

2.2 问题与尝试

回到引言的问题,在讨论更具体的解决方案之前,我们先看看在经过几次大型活动的 pro code 开发后发现了哪些问题,在前期又做了哪些尝试:

2.2.1 活动规则变更效率低

由于活动页为了保证用户体验会集成较多的玩法规则,由于运营无法在活动的密集开发阶段一次性给到准确无误或完全不变的规则说明,在活动上线前,前端需要持续配合更新页面内的活动规则,有时候是换图,有时候是调整文字描述,改动的发布流程较长且影响开发测试效率。

前期尝试:比较泛的解决方法是将前端写死的切图改为从静态资源服务中获取,我们也确实在个别活动中尝试约定过资源路径,产运将资源上传到特定路径后,开发使用约定好的路径来加载资源,但此方案并没有很好地利用现有的低代码平台(如:配置间距、管理资源版本),也存在额外的上手成本和维护成本。

2.2.2 部分常见的需求处理效率低

相似需求总是需要走开发上线的流程,导致开发人力总是紧张,且效率难提高,如:

  • 每次活动都会设计新的榜单样式,这类换皮工作对开发来说耗时且枯燥,影响其他需求的开发进度

  • 直播活动结束后,开发需要按业务流程固化榜单数据,每次都需要将服务端导出的数据替换到代码中,然后再走一遍上线流程

该问题在前期并没有想到很好的处理方法,直到后续复用低代码组件才得以解决。

2.2.3 重复开发组件

前端在大型活动中存在重复开发组件的情况(如:直播榜单组件)。榜单在直播活动中是标配组件,但大型活动页面状态较为复杂,无法直接通过低代码平台配置,导致这类场景我们一直没能复用运营配置的组件,于是又额外开发维护了一套 pro code 场景的榜单组件。

前期尝试:将配置了单个 low code 组件的页面通过 iframe 的形式载入页面框架内,也确实满足了一些活动需求,但同时也发现了其局限性:

  • 组件若涉及弹窗和遮罩,由于弹窗和遮罩都是基于 iframe 页面插入的,难以直接基于宿主页面居中摆放弹窗,遮罩的处理也比较复杂

  • 页面之间可能存在跨域的情况,个别需求得花心思解决

  • iframe 页面完整加载较慢,会重复请求宿主页面加载过的资源,部分请求也并非必要

以上提到的几个痛点,不仅影响我们每次活动的交付效率,也使得前端团队整体的资源利用率较低,前端团队总是处理类似需求得不到成长,也无法推进其它业务需求。

3. 解决方案与实施

秉持着不写新代码就没有新 bugDRY 的开发原则,作者在经过几次 pro code 活动后开始思考:是否有方案可以解决以上问题,让我们可以有精力去做其它更加价值的工作?

3.1 远程组件

2022 年 10 月,首个接入B站远程组件能力(内部名:片段加载器)的猫耳直播活动上线,本次活动在 pro code 页面框架的基础上加载了运营配置的低代码榜单组件、弹窗、活动规则等内容,解决了第一部分提及的所有问题。

图片

3.1.1 原理

顾名思义,远程组件依赖于服务端的组件数据,其包含三大数据:组件 JS 资源、组件 CSS 资源、组件 JSON 参数(运营配置)。组件数据的拉取、组件的渲染等工作,则由客户端的加载器提供支持。

前端研发人员在 pro code 页面框架内集成加载器后,只需传入约定好的页面片段 ID,加载器即可完成页面片段的拉取工作,并复用 low code 页面的渲染器完成渲染工作。

图片

3.1.2 项目工作流

上述编码细节转变的背后,更深层次的转变其实是「开发类页面工作流程」的转变,以及项目人员的工作职责变化。

图片

从新的流程中不难观察到,前端能够在设计稿尚未交付的情况下就提前介入,设计一些适合低代码化的功能模块,然后转交给运营配置使用。前端不仅能够在更专注业务逻辑的情况下提前交付运营也在复杂活动中获得了调整和发布的能力(仅限于部分功能模块),一些运营侧的调整也不必再走前端的发布流程,减少各端沟通返工的情况,项目的整体效率更高。

回到第一部分的具体问题来说,技术侧从以往活动中识别出后期需求、维护需求、效率问题后,可以借助低代码平台将流程功能化,从而实现更顺滑的交付效果。

3.1.3 接入前后的代码对比

旧的代码实现

为了更好地理解效率提升的效果,让我们先看一个典型的旧代码实现示例。这段代码展示了如何编写一个直播榜单组件,一个需要定制的 pro code 榜单通常需要 100+ 行的 CSS 代码,这也意味着前端要等设计资源完全 ready 后才能进开发(给设计也带来了压力),而在活动中需要定制的榜单往往不止一个,且每次活动都需要开发。在活动 DDL 明确的情况下,很容易给前端造成任务堆积,人力不足的问题。

图片

新的代码实现

现在,通过采用远程加载低代码组件的方法,我们大大简化了这个过程。下面是一个使用远程加载低代码组件的示例代码。前端只需一行代码即可加载运营配置的 low code 榜单组件,无需编写繁琐的 CSS 代码,设计同事也可以调低榜单模块的优先级,优先完成其它高优的设计任务。

图片

以下是直播榜单组件在后台系统中的界面截图,展示了运营人员如何通过界面配置而不是编写代码来完成同样的任务。

图片

3.2 接入方案

以下是猫耳前端在接入公司内部低代码平台过程中积累的接入方案。

3.2.1 Pro Code 页面能力对齐 Low Code 页面

为确保 low code 组件能够在 pro code 页面框架内正常运行,我们将一些页面的基础能力封装到了单独的包内,使得不同环境都能够获得一致的效果。

基于 RxJS 实现组件间的数据共享与事件通信

在 low code 页面中,我们基于 RxJS 的 BehaviorSubject 实现了页面级别的数据共享方案,各组件可通过订阅 window 上挂载的 BehaviorSubject 数据流,及时获取全局数据(如:活动状态)。

而在 pro code 页面框架内,在综合考虑开发成本、性能、隔离性(不考虑沙盒环境)这几点后,所以我们直接在页面框架内复用了 low code 页面的初始化流程,确保各组件能够直接接入页面。

图片

内置 Low Code 环境组件,优化加载速度

在 low code 页面中,我们用于初始化页面环境的组件本身也是个 low code 组件,按流程来说,在 pro code 页面内使用时也需要等待加载器的拉取渲染时间,而其余组件则要等初始化完成后才能正常渲染,所以存在一定的阻塞情况。

图片

优化前的默认实现

以下是优化前的页面初始化时序图。

图片

优化后的实现

优化后的时序图已经在远程组件的 3.1.1 原理小节贴过了,可以返回查看。

简而言之,我们将 low code 页面的环境组件直接集成到了 pro code 页面框架内,跟随页面一起构建发布,并且屏蔽了加载器对于环境组件的拉取和渲染逻辑,使得页面能够更快完成初始化。

Pro Code 页面维护所有 Low Code 组件配置数据,支持「合并同类组件的请求」

对于传统的 pro code 页面来说,如果出现需要请求同一接口的同类组件(如:多个音频、多个主播的信息),我们可能只需要在请求时带上 ID 数组即可,但对于 low code 页面来说,为了保证最灵活的制作能力,我们不一定会封装固定布局的组件,更倾向于封装原子组件或者较为基础的业务组件,所以运营拖入页面的可能是一个个独立的组件(同类组件,但配置了多个),每个组件都单独配置了 ID,如果不做处理的话可能会并发出非常多的请求。

图片

图片

对于这种场景,我们以前采取的方案是:在该 low code 组件的 JS 资源被插入执行时(此时渲染器还没有渲染组件),读取页面内配置的所有同类组件,合并配置后统一发出请求,然后借助 rxjs 缓存接口响应数据。等到组件被渲染器实际渲染出来后,再订阅该 rxjs 数据源,实现合并批量请求的目的。

如果现在需要在 pro code 页面框架内实现该场景,对比 low code 页面我们缺少了直接可用的完整组件配置,需要等所有片段都加载完才能拿到完整组件数据。不过这也不难解决,基于已有的 rxjs 数据共享流程,我们只需要对这类组件稍加改造,将直接获取所有组件的配置数据改为订阅所有组件的配置数据。当页面框架逐个获取到组件信息后,逐个塞入 rxjs subject 的组件数据列表,然后组件侧结合 rxjs debounce 操作符(避免频繁请求接口),按一样的流程请求接口获取数据即可。

以下是简化后的请求远程组件并渲染的核心流程。

fetchSegment(pageId)  .then(async (res: any) => {    if (!res || !containerRef.current) {      console.error('segment load failure')      return    }    const { info, render } = res    if (!loadedPageIds.includes(pageId)) {      loadedPageIds.push(pageId)      const newComponentsMap = makeComponentsMap(info.configure?.pageData)      window.MissEvanEvents.next((prev: any) => {        const mergedComponentsMap = Object.entries(newComponentsMap).reduce((acc, [key, value]) => {          acc[key] = (acc[key] ?? []).concat(value)          return acc        }, prev.componentsMap ?? {})        return {          ...prev,          componentsMap: mergedComponentsMap,        }      })    }    render({ container: containerRef.current, needRenderEnvComponent: false })  })  .catch((e: any) => {    console.error('segment load failure', e)  })

3.2.2 规范代码块开发模式

上文在配置类页面已经提到过代码块,代码块由 JS 和 CSS 文件构成,在特定时机插入页面执行,主要执行一些 dom 操作或添加样式。在 pro code 页面框架内集成代码块时我们也做了一些优化工作。

由于代码块的效果依赖 JS 的插入执行,在按需渲染的场景会存在重复插入执行的情况,若忘记清理副作用也更容易出现问题(如:事件泄漏、定时器无法终止)。为优化该问题,我们在 JS 中临时加入了一些代码来检查逻辑是否执行过,以及定时任务是否需要执行等操作,避免出现不必要的问题,并在后续基于 document.currentScript 设计了一套代码块的生命周期函数,用于规范常用代码块的参数、执行、清理。

// 代码块被插入时的定制逻辑
function mount(dependency) {}

// 代码块被销毁时的清理逻辑
function unmount(dependency) {}

ContextManager.initLifecycle({ mount, unmount })

​​​​​​​

我们在 24 年 3 月份将该方案提交给活动中台并进行了比较密切的几次讨论,平台综合各个业务的需求在 24 年 9 月份上线了更加通用的平台级别的代码块开发工具,后续也仍在持续迭代。

4. 成果与效益

4.1 释放前端开发人力

鉴于活动玩法并非一成不变,不同开发者的能力也有区别,单纯的代码量或是工时人天数据并不能准确体现出低代码带来的提升,顶多用于内部预估未来活动的工作量,故以下统计的是各个具有代表性的活动低代码程度,以及组件和代码块的复用情况。由于部分需求比较零散,实际成果可能会比下表更多一些:

图片

从表中可以发现前端自主开发了非常多的代码块,尤其是某些乍一看随便写写也挺快而且没啥复用价值的功能模块,我们也选择将其低代码化交由运营配置。这样做的好处是:不仅大部分内容可以实现脱离设计稿提前开发,还可以摆脱许多后期需求和维护需求,对前端开发来说是一个非常有利的提效模式。

从岗位职责的角度来看,也可以认为代码块开发模式(高频)是在产品正式介入组件设计前(较低频),前端提前将功能模块进行了一部分的抽象设计,便于后续将该功能开发成低代码组件。在代码块开发模式下,运营侧的体验可能弱于组件模式(平台层面已在优化这个问题,如:降低配置难度,提高开发效率),但是仍能够保持一定的交付效率,以及用户侧一致的体验。

4.2 版本管理颗粒度进一步细化

pro code 页面接入 low code 组件后,也带来了一个副产品——页面被打散,版本管理的颗粒度更细了。我们也亲身经历过线上活动出现紧急问题,产运直接调整发布,快速缩小影响范围然后开发再排查修复的情况。远程组件让我们在应急处理线上问题时又多了一种手段。

5. 结语

以上是猫耳前端对于活动低代码场景的探索和经验总结,欢迎在评论区继续讨论,一起挖掘业务提效的方法。在此感谢猫耳前端组以及 EVA 平台组一起参与建设的同事们,特别感谢 EVA 平台组的璇儿、琥珀草、谷风长道、小白白川、V、Fryderyk 等同事对我们提供的大力支持。对 bilibili 活动中台系统设计感兴趣的小伙伴可以继续移步查看这篇新活动平台建设历程与架构演进。

   -End-

     作者丨Helson、Rui

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习 Day02,matplotlib库绘图

1.matplotlib图像结构 容器层:画板,画布,坐标系辅助层:刻度,标题,网格,图例等图像层:折线图(主讲),饼图,直方图,柱状图等…

MySQL中有哪几种锁?

大家好,我是锋哥。今天分享关于【MySQL中有哪几种锁?】面试题。希望对大家有帮助; MySQL中有哪几种锁? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中,锁是用于确保数据的一致性和并发控制的机…

Unity单例模式更新金币数据

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在游戏开发中,单例模式非常适合用于管理全局唯一的数据,比如玩家的金币数量。通过使用单例…

【javaEE】多线程(进阶)

1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…

Vue3实战学习(Element-Plus常用组件的使用(输入框、下拉框、单选框多选框、el-image图片))(上)(5)

目录 一、Vue3工程环境配置、项目基础脚手架搭建、Vue3基础语法、Vue3集成Element-Plus的详细教程。(博客链接如下) 二、Element-Plus常用组件使用。 &#xff08;1&#xff09;el-input。(input输入框) <1>正常状态的el-input。 <2>el-input的disable状态。 <3…

C++ 链表List使用与实现:拷贝交换与高效迭代器细致讲解

目录 list的使用&#xff1a; 构造与赋值 元素访问 修改操作 容量查询 链表特有操作 拼接&#xff08;Splice&#xff09; C11 新增方法 注意&#xff1a; stl_list的模拟实现&#xff1a; 一、链表节点设计的艺术 1.1 结构体 vs 类的选择 二、迭代器实现的精髓 2…

知乎后台管理系统:数据库系统原理实验1——数据库基础概念

实验背景 通过练习绘制语义网络&#xff0c;加深对于基本概念之间关系的理解和掌握。掌握在VISIO中绘制能准确表达基本概念之间关系的语义网络的技能。了解并比较数据模型的Chen’s表示法和UML表示法。理解关系模型设计中的完整性约束的重要性。掌握在Linux操作系统下远程访问…

docker compose 以redis为例

常见docker compose 命令 》》注意这个是旧版本的&#xff0c;新版本 docker 与compose 之间没有 - 新版本的 docker compose 把 version 取消了 &#xff0c;redis 默认是没有配置文件的 &#xff0c;nginx&#xff0c;mysql 默认是有的 services:redis:image: redis:lat…

ES C++客户端安装及使用

1. ES 介绍 Elasticsearch &#xff0c; 简称 ES &#xff0c;它是个开源分布式搜索引擎&#xff0c;它的特点有&#xff1a;分布式&#xff0c;零配 置&#xff0c;自动发现&#xff0c;索引自动分片&#xff0c;索引副本机制&#xff0c; restful 风格接口&#xff0c;多…

【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

应急响应--流量分析

&#xff08;一&#xff09;Cobalt Strike流量特征分析 1.HTTP特征 源码特征&#xff1a; 在流量中&#xff0c;通过http协议的url路径&#xff0c;在checksum8解密算法计算后&#xff0c;32位的后门得到的结果是92&#xff0c;64位的后门得到的结果是93&#xff0c;该特征符…

自然语言处理:高斯混合模型

介绍 大家好&#xff0c;博主又来给大家分享知识了&#xff0c;今天给大家分享的内容是自然语言处理中的高斯混合模型。 在自然语言处理这个充满挑战与机遇的领域&#xff0c;我们常常面临海量且复杂的文本数据。如何从这些数据中挖掘出有价值的信息&#xff0c;对文本进行有…

【C++指南】一文总结C++类和对象【中】

&#x1f31f; 各位看官好&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f680; 今天来学习C类和对象的语法知识。注意&#xff1a;在本章节中&#xff0c;小编会以Date类举例 &#x1f44d; 如果觉得…

再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特别之处,还有发展方向

三年前我们通过 《Flutter Riverpod 全面深入解析》 深入理解了 riverpod 的内部实现&#xff0c;而时隔三年之后&#xff0c;如今Riverpod 的主流模式已经是注解&#xff0c;那今天就让我们来聊聊 riverpod 的注解有什么特殊之处。 前言 在此之前&#xff0c;我们需要先回忆…

Go语言集成DeepSeek API和GoFly框架文本编辑器实现流式输出和对话(GoFly快速开发框架)

说明 本文是GoFly快速开发框架集成Go语言调用 DeepSeek API 插件&#xff0c;实现流式输出和对话功能。为了方便实现更多业务功能我们在Go服务端调用AI即DeepSeek接口&#xff0c;处理好业务后再用Gin框架实现流失流式输出到前端&#xff0c;前端使用fetch请求接收到流式的mar…

docker不停机部署

背景 最近做大疆项目时&#xff0c;后台更新部署时&#xff0c;机场和无人机就会掉线。设备自动重连注册时间比较长&#xff0c;应用长时间不可用。所以需要灰色发布服务。docker-compose的swarm模式可解决此问题。 服务构建脚本Dockerfile # 使用官方Java基础镜像&#xff…

ZLG嵌入式笔记 | ZLG核心板散热设计指引

在嵌入式系统设计中&#xff0c;散热是影响处理器性能与稳定性的关键问题。本文聚焦于高端嵌入式处理器的散热设计&#xff0c;探讨核心板的热设计与系统级热设计方法&#xff0c;以及导热材料和布局的建议&#xff0c;为解决高温问题提供参考。 用高端嵌入式处理器设计系统&am…

[Java]使用java进行JDBC编程

首先要从中央仓库下载api(类似驱动程序)&#xff0c;为了链接java和mysql 下载jar包&#xff0c;需要注意的是jar包的版本要和mysql保持一致 下面是新建文件夹lib&#xff0c;把jar包放进去&#xff0c;并添加为库 sql固定的情况下运行 import com.mysql.cj.jdbc.MysqlDataSo…

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…

fiddler+雷电模拟器(安卓9)+https配置

一、fiddler配置 1、开启https代理 2、根证书安装&#xff1a;导出证书系统安装 二、模拟器设置 1、设置网络桥接模式 【点击安装】提示安装成功后保存即可 2、开启root&#xff08;开启adb远程调试&#xff09; 3、开启磁盘写入 4、设置WLAN代理 5、证书安装&#xff1a;物…