兼顾效率和性能!快手低代码平台在大型活动中的技术实践!

一、大型活动所面临的技术挑战

CNY(春节活动)是快手重要的年度专项之一。平台在春节期间推出多种互动玩法,内容会场作为预热、除夕和留存阶段的核心载体,先后支撑了"快手有年味"、"老铁晚会"、"龙之页"、"明星陪你过大年"等多项活动。这些页面以内容消费为主,致力于将内容与玩法创新结合,以更好地实现业务目标。

快手低代码搭建平台(简称"积木")是快手核心的运营活动页面构建基础设施,目前已承担90%以上的活动页面搭建工作。在2025年CNY内容会场中,共包含18个会场和40多个页面。作为技术支撑方,为高效、高质量支持业务团队,需重点解决以下问题:

  • 高效方面:尽可能通过无代码方式满足需求。这就要求搭建方式足够灵活、易于组合,并对无法直接搭建的创新需求提供快速定制开发能力。

  • 高质量方面:保障用户满意度。需确保页面性能达标,提供流畅的视频与直播消费体验,并在多端实现一致且高还原度的视觉表现。

在这一背景下,积木平台主要面临以下四大技术挑战:

挑战一:复用与创新的天然矛盾

低代码平台普遍面临复用与创新之间的内在矛盾,主要体现是平台设计层面和业务创新层面的冲突。

尽管积木平台已积累300多个组件,覆盖多数常规业务场景,但在支持大型"创新型"活动方面仍可能存在不足。增加组件数量是否能彻底解决该问题?理论上是可行的,但是需求是无止境的,而组件开发人力资源有限。持续扩充组件数量带来的边际收益已明显递减------功能覆盖率与组件复用率逐渐趋于平稳。盲目增加组件并非可持续方案,需探索新路径以支持"长尾"创新需求。

接下来将逐一介绍我们是应对上述挑战的解决方案。

挑战二: 页面复杂度导致的性能瓶颈

首先,低代码平台搭建的页面在性能上本身就有一定的天然劣势,主要原因有以下两点。其一:组件复用和通用性设计导致逻辑冗余,增加了运行时开销。其二:动态组件组合使得针对单页面的性能优化变得复杂。以内容会场活动页面为例,其组件数量常超过300个,涉及40余种组件类型,进一步引发以下性能问题:

  • 组件JavaScript文件加载集中,网络请求频繁,影响首屏加载性能;
  • 多组件状态管理和JS执行产生Long Task,阻塞主线程渲染,导致页面卡顿。

挑战三:多播放器并发渲染的性能挑战

内容会场通常包含大量视频播放器,某些页面中甚至同时存在数十个。播放器数量与GPU及内存消耗呈正相关,过多播放器可能导致浏览器内存耗尽,甚至引发应用崩溃。因此,解决多播放器环境下的性能问题至关重要。

挑战四:多端响应式布局适配技术挑战

原有布局方案采用基于 vw 的等比缩放布局策略,在常规屏幕上表现良好,但在 Pad 和折叠屏等大屏设备上,因活动规范要求需限定最大展示区域,等比缩放会导致内容过宽,影响视觉效果。相比于 rem 单位可以通过设置根元素宽度来控制最大布局宽度,vw 是基于视口宽度计算的,难以有效约束内容区域,因此成为响应式适配中的技术瓶颈。

接下来将逐一介绍我们是应对上述挑战的解决方案。

二、如何兼顾复用和创新?

面对代码逻辑与业务需求的无限性,我们采用低代码能力对无码搭建进行有效补充。通过"部分搭建+部分定制"的混合开发模式,最大限度地复用平台现有能力,从而显著提升活动产出的整体效率。具体而言,我们推行"90% 搭建 + 10% 定制"的开发策略,实现标准化与定制化的深度融合,真正做到"你中有我,我中有你"。

对低代码平台而言,复用与创新之间存在一定程度的天然矛盾,但这一矛盾并非不可调和,关键在于实现动态平衡。其本质是标准化与灵活性、效率与差异化之间的动态博弈。我们的目标并非消除矛盾,而是构建一个"以复用支撑创新,以创新反哺复用"的健康生态,从而服务更多样的活动需求。通过建立"创新 → 沉淀 → 复用 → 再创新"的闭环机制,我们力求在短期应对矛盾,在长期实现共生。

  • 短期应对:复用保障基础效率,局部创新突破场景边界。
  • 长期共生:创新成果反向沉淀为可复用资产,推动平台能力进化。

2.2 积木平台:构建灵活高效的技术基座

2.2.1 组件原子化与容器化架构设计

随着业务复杂度的提升,传统粗粒度组件架构已无法满足多样化需求。积木平台采用组件原子化与容器化的架构设计,将复杂组件拆解为最小功能单元,通过组合模式实现灵活搭建。

组件:具备独立功能的最小单元,可直接实现某种业务逻辑或交互功能,如按钮、视频、图片等。容器:用于组织和布局其他组件(或子容器)的特殊组件,本身不直接提供业务功能,而是通过结构化嵌套实现页面或模块的层次化管理。比如聚光灯容器,含有滑动 + 缩放的能力,里边可以放置任意的非容器组件。

通过组件原子化 + 容器化的组合方式,使得搭建更灵活。例如:一个支持左右滑动并带有缩放效果的组件,可以将其拆分为"图片组件" 和 "聚光灯容器"这两个基本单位。基于这两类稳定单元的不同组合,能够衍生出丰富的功能玩法,真正实现"以不变应万变"。

2.2.2 母版同步提升搭建效率

需指出的是,组件原子化这类细粒度拆分方式,在某些场景下可能降低搭建效率,反而不如粗粒度组件配置便捷。例如,当用户需要配置一个包含头像和关注按钮的列表时,若每个卡片都需逐一拖拽配置,尤其当数量达到数百个时,重复劳动将极其繁琐。

为此,我们引入"母版"机制,通过对原子组件进行再组合,有效缓解细粒度拆分带来的操作负担。母版可生成子版,用户通过调整母版即可统一控制所有子版的UI样式与布局,实现一键同步。具体机制包括:

  • 母版中的配置属性可同步至子版(包括多级子版);
  • 母版中定义的事件也会同步至子版,事件"作用域"仍限于对应子版;
  • 若某子版已修改自身属性,则该属性不再随母版更新而同步。

2.2.3 逻辑编排串联组件

我们通过逻辑编排功能,以可视化方式灵活串联组件间的业务逻辑,显著提升复杂交互的搭建效率。例如,在"用户点击直播间预约按钮成功预约后自动触发抽奖"这一场景

中,逻辑编排可以清晰、高效地定义该流程。

2.2.4 定制开发

针对个性化需求,平台提供三大核心能力:

  1. 定制化扩展能力:为增强组件的适应性,支持通过代码注入方式对组件进行扩展,使其在保持核心能力的基础上,能够灵活响应个性化需求。

2.组件白盒化Fork能力:开发者可直接基于现有组件进行修改,通过远程编译打包并上线,还可将调整后的组件发布至组件市场,供他人二次编辑或复用。这样不仅提升开发效率,也促进了组件生态的持续完善。

3.对外开放能力:提供轻量、临时性的开发方案,帮助业务快速上线并验证效果。技术实现上,开发者可在浏览器中直接编写代码,无需配置本地环境,实现"开箱即用"。代码提交后经由远程编译服务打包,最终发布至CDN。C端渲染时,将动态加载该定制组件,并融合平台的基础能力------如 Context、Bridge 与数据埋点等------使开发者既能快速实现定制,又能复用平台的通用底层能力。Context:用于识别并兼容不同的运行环境(如快手APP、快影APP、回森等)。Bridge:为 H5 提供与客户端交互的统一通道。

此外,平台引入AI能力进一步降低定制开发门槛,提升代码复用与功能实现效率。例如,开发者可通过自然语言指令,要求AI在按钮点击时前置调用某个接口,并在成功后再执行后续逻辑。此外,AI还可辅助完成组件的Fork与代码改写,显著提升定制开发的效率与质量。与此同时,我们也提供了VS Code的插件,开发者可以在自己的IDE 中进行定制开发。

三、高性能渲染架构与优化策略

上文提到在大型运营活动场景中,页面组件数量往往达到约300个,涉及约40种组件类型。此类多组件页面在默认按序加载和执行JS文件的情况下,容易导致整体渲染性能下降。其背后主要原因是组件加载频繁触发Reflow、Repaint和组件同步渲染,JS 执行存在Long Task,导致卡顿。针对此问题,我们采用SSG 静态生成方案以及组件渲染优化策略,下文将详细介绍细节。

3.1 SSG 静态生成方案

相较于客户端渲染(CSR)和服务端渲染(SSR),静态站点生成(SSG)更适用于低代码搭建类页面。这类页面结构通常基于现有组件组合而成,在构建阶段即可确定,无需复杂运行时逻辑,因此非常适合在编译时生成静态内容。

采用SSG的核心目标是"扬长避短":

  • 将尽可能多的运行时计算提前至发布阶段完成;

  • 基于页面结构相对固定、首屏动态内容较少的特点,充分发挥SSG在性能上的优势。

SSG 实现过程如下:

上面是对整个页面做的SSG,但是在实际渲染过程中,用户优先看到的是首屏的内容,可以进一步优化首屏的性能。优先只渲染首屏的组件,当首屏组件渲染完毕之后,再渲染非首屏组件。

那么,具体怎么确定首屏组件呢,我们这里采用的方案主要有以下几个方面。需要考虑以下三点:

  • 根据配置的高度基准值做参考,小于基准值的会被标记为首屏元素。但是会排除掉像弹窗、抽屉、非默认激活的Tab等容器中的元素。
  • 相对屏幕定位的元素。
  • 和首屏元素有绑定关联关系的元素。比如首屏的预约人数的组件,依赖非首屏的预约组件,那么非首屏的预约组件也需要提前渲染。

以下图节点为例,受引用关系和定位影响,部分非首屏元素也需在首屏进行渲染:

首屏SSG流程如下:

3.2 组件渲染优化策略

编辑器设计:

引擎设计:

3.2.1 组件分级渲染

为了进一步提升 fmp(首次有效绘制) ,我们对组件做了分级渲染,在编辑器中保存时,提前计算好哪些组件可能在首屏,需要对组件配置做标记,将组件主要分了以下三个级别:

  • 首屏组件:组件JS采用同步加载方式、组件样式内联。
  • 次屏组件:组件JS采用异步加载方案、样式在组件加载完毕后动态注入。
  • 按需组件:比如嵌套在未激活Tab中的组件、弹窗、抽屉等组件。

3.2.2 组件异步渲染

我们采用多项策略优化加载性能:

  • 预加载:
    • 首屏组件js文件采用 preload 预加载。
    • 非首屏组件采用 prefetch 预加载,让其他必要资源提前加载。
  • Defer与Async结合方案:
    • 使用 defer 实现JS异步下载,但仍可能因顺序执行造成阻塞;
    • 单纯使用 async 可能导致依赖未加载完成而报错;
    • 最终方案:公共依赖文件采用 defer,组件的代码文件采用 async。具体做法是公共依赖文件SSG时直接输出到HTML文件中,组件文件在Engine中采用动态创建的方式。
  • JS文件动态激活:
    • 为避免某些浏览器中 preload/prefetch 失效导致重复请求,SSG 阶段将 script 输出为 type="text/plain",在适当时机再切换为 type="text/javascript" 执行,例如:
xml 复制代码
<script src="engine.js" defer></script>
<script src="context.js" defer></script>
<script class="reload-script" type="text/plain" src="A.js" async></script>
<script class="reload-script" type="text/plain" src="B.js" async></script>

3.2.3 首屏样式合并

针对多组件场景,动态插入style导致频繁Reflow、Repaint 的问题,在SSG阶段,会将首屏的组件css直接输出到HTML文件中,生成后的样式如下。

xml 复制代码
<style id="jimu-pre-style">
 // SSG 样式
</style>
  
 
<style>
 // 对首屏的组件样式进行合并,直接输出在HTML中
</sytle>

3.2.4 组件体积优化

一方面,我们将工具链从 webpack 平滑迁移到 rspack,rspack 在构建速度,体积压缩方面都有了比较大的提升。另一方面,采用 autopolyfill 的方案按需引入 polyfill 产物,使得组件体积大幅减小。综合来看,平均产物大小减少 65.91%,平均产物 Gzip压缩 后大小减少百分比 68.37%。

四、多播放器调度引擎设计

内容会场通常包含大量视频和直播组件,多播放器并发渲染对页面性能构成严峻挑战。为此,我们设计了一套智能播放器调度引擎,以系统化地应对播放冲突、性能开销与用户体验等问题。

针对这个问题,解法也比较明确,就是采用单实例。在单实例播放模式下,播放器切换时需销毁原有实例,因此必须保存其播放状态,确保再次激活时能够实现无缝续播。播放器实例销毁后画面会消失,若不做处理将严重影响用户体验。我们考虑了两种方案:

  • 使用封面图:可能因频繁切换导致视觉闪烁,体验较差;
  • 将当前画面保存为静态图像:优先选用该方案,在播放器销毁前将当前视频帧导出为图片并展示。

此外,我们建立了如下机制实现播放器的智能调度:

  1. 播放器收集与排序:将所有播放器实例收集到统一队列中,按其在页面中的位置(如 top 值)排序,确立播放优先级;

  2. 播放候选选择:优先选择"漏出比例"为1(即完全进入视口)的播放器;

  3. 播放状态保持:若已有播放中的实例,则不中断当前播放;

  4. 用户行为优先:用户主动点击某播放器时,立即播放该元素,不受漏出比例限制(需记录该操作时的漏出比例,后续根据比例变化动态调整是否切换播放)。

然而,在引入聚光灯、弹窗、抽屉等动态容器后,播放决策变得更为复杂。尽管可通过事件配置(如"聚光灯激活时播放指定视频"或"弹窗打开时播放视频")实现精准控制,但也带来了配置复杂度上升的问题。

若不配置事件,可能出现以下问题:

在聚光灯轮播过程中,因中间元素漏出比例暂时小于1,引擎可能错误地播放下方视频,而非用户预期中的聚光灯内容。

动效(如变换、位移、缩放、透明度变化等)会影响元素位置与可见性,进而干扰播放决策。为解决该问题,我们监听动画结束事件。为确保动效结束后正确选中聚光灯内的元素,我们优先选择与当前播放元素距离最近的候选元素,这更符合用户视觉动线,也避免因 IntersectionObserver 返回顺序混乱而误判。

scss 复制代码
const animation = element.getAnimations();
animation.addEventListener('finish', handleAnimationEnd);
animation.addEventListener('cancel', handleAnimationEnd);

用户滑动页面时,若实时切换播放器,在聚光灯等动效场景中可能因中间状态频繁触发销毁与重建。因此,我们引入延迟处理机制(pending),避免中间过程被感知,既提升切换效率,也减少不必要的性能开销。

理想的浮层播放策略是允许新出现的上层元素抢占播放权,但这会与既定统一策略冲突,并可能违背用户预期。传统做法是通过事件或容器感知实现播放中断,但会引入组件间耦合。我们采用的解耦方案是:当检测到当前播放元素被遮挡时,自动切换到位于遮挡物上层的播放器。通过如下方式判断元素层级:

javascript 复制代码
const { x, y } = target.getBoundingClientRect();
const elements = document
        .elementsFromPoint(Math.max(x + 1, 0), Math.max(y + 1, 0));

未来随着标准发展,也可借助 trackVisibility 等新特性进一步优化可见性追踪。低代码平台中的视频播放调度远比通常情况复杂,本文仅勾勒了核心思路与实现路径。

五、多端布局适配

在大型活动中,设计规范通常要求页面在 Pad、折叠屏等宽屏设备中限制最大宽度,实现两侧留空的视觉效果。然而,平台原有布局方案采用 vw 单位,其计算依赖于视口宽度,无法像 rem 一样通过根元素字体大小限制整体布局宽度,因此需引入新的适配机制。我们调研了行业内多种适配方案,结合其优缺点及业务需求后认为:CSS calc 兼容现有布局,维护成本低,但性能仍需进一步验证。为验证性能表现,我们针对两类典型页面进行了多机型测试,实验结果表明,在超复杂页面(包含组件385个,节点1310个),Android 性能无明显差异,iOS 内存占用增加约 80MB。在复杂页面,选取历史中组件较多的页面,含组件 335 个,节点 1240 个的情况下,Android 和 iOS 性能表现均无显著差异。

综合多方数据,最终评估后,选择基于 CSS calc 的实现方案。

在技术实现层面,我们引入一个 CSS 自定义变量 --jimu-responsive-ratio,默认值为 1,并根据预设最大宽度动态计算缩放比例:

ini 复制代码
const WIDTH_MAX = 500;
const scale = WIDTH_MAX / window.screen.width;
const rootNode = document.documentElement || document.querySelector(':root');
rootNode.style.setProperty(CSSRootVar.RESPONSIVE_RATIO, `${scale}`);

同时调整渲染逻辑,将原有的 vw 单位替换为 calc 表达式,例如:

css 复制代码
left: `calc(${num}vw*var(${CSSRootVar.RESPONSIVE_RATIO}, 1)${offset})`;

由于 fixed 定位基于视口,内容区域限制最大宽度后可能出现元素偏移。为此我们引入偏移量变量进行补偿:

ini 复制代码
const offset = (clientWidth - MAX_WIDTH) / 2;
rootNode.style.setProperty('--jimu-responsive-offset', `${offset}px`);

在样式生成过程中,对使用 fixed 定位的元素额外添加该偏移量:

六、总结与展望

本文以CNY内容会场为例,系统阐述了积木平台在架构设计、性能优化与系统集成等方面的技术实践与落地成果。通过体系化的技术架构,积木平台有效平衡了高效搭建与业务创新之间的关系,通过SSG静态生成、组件分级渲染与异步渲染等关键技术,解决了300+组件加载的页面性能瓶颈,实现了大规模组件场景下的流畅体验。

单一技术问题的解决方案往往并不复杂,但当其置于低代码平台这一复杂架构背景下时,技术挑战呈指数级上升。期望本文所分享的经验与思路,能为面临类似问题的技术团队提供有益的参考。展望未来,我们将持续探索积木平台与AI技术的深度融合,进一步拓展低代码平台的能力边界,为更广泛的业务场景赋能。

【END】

相关推荐
WebInfra3 小时前
📱开源 AI 工具驱动 iOS 自动化 、接入全新 Qwen 模型 - Midscene v0.29 发布
前端·ios·测试
乖女子@@@3 小时前
React-props的children属性
前端·javascript·react.js
OEC小胖胖3 小时前
组件化思维(下):表单与交互组件,倾听用户的心声
前端·微信小程序·小程序·微信开放平台
八月十八3 小时前
React常用Hooks及使用示例大全
前端·javascript·react.js
狼爷3 小时前
前端项目从 Windows 到 Linux:构建失败的陷阱
前端·node.js·angular.js
1024小神3 小时前
vitepress多语言实现第一次跟随浏览器,第二次不跟随
前端
叫我詹躲躲3 小时前
🚀 震撼!10道DFS&BFS神级题目让你的算法能力飙升300%
前端·leetcode
ssshooter3 小时前
WebGL 切换 Shader 的策略
前端·webgl
WDyinh3 小时前
积分球领取补位动画实现
前端·javascript