当前位置: 首页 > news >正文

每日必抢小程序下单总结

每日必抢小程序下单总结

作者:穿流

在数字化时代背景下,电商平台不断拓展其触达用户的边界,而“每日必抢小程序”正是这一趋势下的产物。本文深度剖析了这款小程序如何在支付宝、夸克等非淘宝 App 端为用户提供近似淘宝 App 的购物体验,通过整合营销、搜索、交易等核心电商能力,实现在多平台的无缝衔接。

一、背景

每日必抢小程序是指在非淘宝 App 端上面向消费者提供电商服务的小程序,具备的营销、搜索、交易、履约、客服等核心电商能力,基于淘宝 App 提供的能力底座,让消费者可以在非淘宝 App 端享受到接近淘宝 App 的线上购物体验。

在支付宝上做的小程序叫每日必抢,在夸克上叫省钱集市。

1.1 下单

小程序下单的产品能力是依托淘宝的交易底座,搭建了一条小程序的链路

1.2 产品架构

产品能力上主体跟淘宝一致,同时延伸了一些特色业务场景,比如会员购,花呗购和商家积分购(下图橙色框),这些新的业务场景也给我们带来了一些挑战。

二、演进历史

2.1 DX 方案

DX 全称 DinamicX,它用 XML 的语法来描述视图 UI,广泛用于手淘 App 客户端,比如首页,下单和购物车等场景,解决在不发版的情况下动态下发 UI 布局,以及部分逻辑能力来支持业务的快速更新迭代,提升工作效率。

由于历史原因,小程序 1.0 使用 DX 来写的,然后将 DX 构建成 JSON 形式组件树,小程序从 DX 平台拉取组件树后映射到小程序组件后进行渲染,渲染过程包括:处理 DX 样式属性,数据属性和绑定事件等,具体流程见下图:

可以看到渲染阶段会有一个拉取 DX 组件树模版的过程,会影响首次渲染的速度,需要内置模版来解决。而且这是一套运行时的方案,需要在小程序侧动态解析组件树并递归渲染,同时由于样式和数据都是动态设置的,运行性能上会有一些影响。

每一个 DX 原子组件都需要有一个小程序组件对应,同时每一个 DX 组件的属性都需要有对应的小程序实现。举个例子,DX 上有一个 InputView 的 DX 组件,然后它支持一些样式属性,数据属性以及事件属性,我们需要写一个对应的小程序 InputView 组件来实现:

1. 每一个样式属性都需要写一个映射函数转化为 css 的属性(this.setStyles)

2. 每一个数据属性都需要手动设置(this.setData)到 data 里使用,

DX 的 InputView 组件: 

<InputView  <!-- 样式属性 -->        height="46np"        width="match_parent"  <!-- 数据属性 -->        text="测试"        placeholder="这是一个文本"  <!-- 事件属性 -->onAppear="@appearExpose{@data{subSection.home.subSection.searchBox}}" // 事件/>

小程序 InputView 的实现: 

Component({  methods: {    triggerChange(e) {      this.dinamicXEventHandler({        type: 'onChange',        value: deepGet(e, 'detail.value')      });    },    onChange(propValue) {      this.events.onChange = propValue;    },    text(propValue) {      this.setData({ value: propValue });    },    placeholder(propValue) {      this.setData({ placeholder: propValue });    },    textColor(propValue) {      this.setStyles(        {          color: Dinamic.colorParser(propValue)        }      );    }  }})

一个简单的 InputView 都需要这么多胶水代码,更别说有更复杂属性的自定义组件了。



DX 诞生于客户端技术,由于客户端的发版频率受限,DX 可以很好满足了“动态化”的诉求,这也是之前选择 DX 的最主要原因。不过在小程序侧,发版相对比较自由,DX 的优势就不存在了,反而带来了编码成本和性能损耗的问题,于是我们在考虑放弃 DX 的方案。

2.2 RAX 方案

后端需要做应用迁移,我们也准备一起升级前端的架构,选择 Rax 主要原因是它拥有跨小程序端的特性,满足跨端诉求(上面提到的支付宝和夸克),同时语法层面相比 DX 是前端更加熟悉的,所以选择了这套方案。

Rax 体验还是比较好的,没有 DX 版本的动态模版加载过程,页面可以做到直出。当时我们也是跑了一段时间,不过随着业务个性化需求的逐渐增多,发现支付宝上一些新的小程序特性无法支持,因为 Rax 目前处于维护状态,不新增新功能



同时我们发现 Rax 这套方案会有构建体积过大的问题,包体积可以达到 600KB,同等规模原生小程序只需要 200KB,影响加载性能。同时由于它是一个应用层的方案,上层用 JSX,然后会转换为 vdom,然后将 vdom 的变化通过 setData 同步给原生小程序,存在 vdom 转换到小程序视图的性能损耗。

来源自掘金文章《 Rax 小程序运行时方案解密与思考》--逆葵

开发体验也会有一些问题,比如二次构建(Rax 构建成小程序的 JS 文件,小程序 JS 自身的构建)速度慢,每次保存都要等待一会儿才能看效果。

基于以上问题,我们开始考虑是否可以直接迁移到原生小程序。

2.3 原生小程序方案

Rax 不再维护,其实我们是可以换一个跨端框架的,比如 Uni-App,Taro,不过经过团队的讨论,最后我们还是选择原生小程序方案。

为什么是原生而不是跨端框架?

首先,小程序是没有一个标准化的组织,随着时间推移,各家小程序(微信,支付宝、抖音等)的差异肯定是越来越大,像 Rax 这类的跨端框架需要“抹平”的成本会越来越高。而且抹平一般会采用交集的方式进行抹平,会导致我们无法利用到各个小程序平台的最全能力。

跨端框架拥有“Write Once, Run everywhere”的好处,对于 0 到 1 探索阶段的项目比较适合,可以快速铺到各个市场,但是无法适用于每日必抢这类对性能、体验、深入融合各端生态有着高要求的项目,基于此我们还是决定拥抱原生建设下单方案。

奥创协议

在介绍下单方案之前先了解下奥创协议,它的作用是用来描述前端页面的渲染协议,它提供了一套机制,让前端开发只关心渲染,业务逻辑统一收敛到后端,同时它统一了前后端交互的三种方式,render(首屏渲染)、async(异步刷新)和 submit(提交)。

这套方案非常适合下单,购物车这类业务逻辑复杂的表单型页面

举个例子,用户在下单页购买数量加 1 需要重新计算价格,如果这个逻辑放在前端,后端需要下发限购规则、优惠规则、库存等数据,前端需要按照限购规则判断是否可以加,还需要按照优惠规则重新计算价格,提交的时候后端还需要算一遍,意味着前后端需要写两份相同的逻辑。

随着业务逻辑越来越复杂,两份逻辑需要保持一致变得越来越难做到,将逻辑收敛到后端,前端只关心渲染成为了大势所趋。有了奥创协议,前端只需要按照协议渲染即可,业务逻辑可以收敛到后端。

技术架构

基于奥创协议,自建的一套原生小程序下单方案。原生小程序方案大致分为三层架构:

1. 奥创协议搭建层:搭建下单页布局和模型,产出页面 schema。

2.  后端服务层:基于页面 schema,组装业务数据,产出符合奥创协议的数据。

3. 小程序页面层:基于奥创协议数据渲染页面,具体分为如下四个模块:

  • 渲染逻辑模块:继承奥创渲染 SDK,负责符合奥创范式的渲染逻辑,后面会详细介绍。

  • 服务模块:负责跟服务端的数据交互,定义请求和返回处理逻辑

  • 业务逻辑模块:处理用户行为触发后的副作用逻辑,比如触发 async 方法,触发 submit 方法,组件联动。

  • 视图模块:视图层,只负责 UI 的渲染。

前端奥创渲染 SDK

奥创渲染 SDK 主要是提供一个通用的基于奥创的渲染 SDK,下单、购物车等场景可以使用这个 SDK 快速搭建页面,分为两个主要模块:

1. 渲染逻辑模块:一方面负责页面初始化,处理跟后端交互逻辑,比如发送首屏请求;另外一方面是监听奥创数据变化从而渲染页面。

2. 主控制模块(Context):提供跟奥创相关的业务逻辑 API,包含协议操作,状态管理以及日志管理等模块。



业务集成奥创渲染 SDK,同时注册业务逻辑控制模块 和 服务模块,然后可以利用 Context 开放的 API 可以进行奥创数据进行修改。

业务效果

迁移到原生小程序方案后,性能的提升也非常明显,首先包体积降低了 66.6%,同时录屏来看加载性能也提升不少。iPhone 14 打开速度提升 38%。

三、业务挑战

由于业务逻辑收敛到后端,前端基本不会有业务逻辑,不过跟支付宝合作会员购的项目打破了这个规则。

由于后端无法直接调用支付宝查询积分接口,需要从前端来调用,然后拿到积分之后需要在价格区域加上积分信息,如下图红框的积分区域是支付宝积分接口返回的。

3.1 方案 1:会员购组件内处理

会员购场景会下发会员购组件,一个想法就是在会员购组件通知更新组件数据,可以让逻辑收敛到会员组件里,可以让业务逻辑高内聚。

不过这个方案存在异步接口竞态问题,由于会员购组件查询积分是异步的,如果在异步查询过程中用户行为触发了异步接口,不好控制积分查询异步接口和 async 接口的返回顺序,如果积分查询接口先返回,async 接口后返回,就会出现覆盖积分信息的问题。

3.2 方案 2:查询积分放到请求返回之后做

为了解决上面竞态问题,我们把积分查询逻辑放到请求返回之后做,这样子避免了积分查询数据被覆盖的问题。

随着后续场景的接入,在服务模块处理数据成为了一个研发范式。比如下面支付宝红包也是调用支付宝接口查询的,调用时机是在 render 和 async 接口返回之后。

四、开放扩展点(建设中)

未来可预见的问题:

1. 类似会员积分、支付宝红包等功能场景会越来越多,这些场景都会同时修改一份奥创协议,如何管理好功能点的执行顺序成了比较大的问题。

2. 同时随着更多端接入,每一个端功能点诉求不一致,如何做到功能点快速可插拔也是需要考虑的问题。



解决思路:

提供扩展点,让这些功能点可以通过能力包的方式注册进来。一来通过能力包让功能点的逻辑收敛,更内聚,二来这套下单的范式不受小程序端 DSL 的影响,后续可以方便应用到其他端。



扩展点主要可分为两个:

1. 业务逻辑处理模块:支持注册不同能力包,能力包包含两部分,一个是组件,一个是组件对应的业务逻辑(核心是联动逻辑)。

2. 服务模块:提供一些生命周期钩子比如请求开始,返回结束,数据渲染完成后等,同时管理各个能力包的执行顺序(可以在能力包里面声明执行优先级)。

具体见下图红色框区域的部分:

五、结语

本文详细回顾了每日必抢小程序的下单系统演进历程,着重介绍了各阶段的技术选型、架构设计、遇到的挑战及解决方案。展望未来,其核心在于构建开放扩展点机制,旨在通过能力包注册的方式,灵活应对日益增多的功能场景与不同端的个性化需求,进一步提升系统的可维护性与扩展性。这一系列技术革新与实践,不仅为每日必抢小程序的持续优化与创新提供了强有力的技术支撑,也为业界在小程序开发领域的探索提供了宝贵经验与启示。

参考资料

[01] 《Rax 小程序运行时方案解密与思考》

https://juejin.cn/post/6890428926540283918

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++——深部解析哈希
  • 助力汽车零部件产业发展,2025 第十二届广州国际汽车零部件加工技术及汽车模具展览会与您相约“羊城”广州
  • 了解elementUI的底层源码, 进行二次开发
  • SpringBoot项目获取统一前缀配置以及获取非确定名称配置
  • python画图|3D surface基础教程
  • 【诉讼流程-健身房-违约-私教课-多次沟通无效-民事诉讼-自我学习-铺平通往法律的阶梯-讲解(1)】
  • tensor 的运算(加法、点乘、矩阵乘法)
  • node.js框架StrongLoop快速入门实战
  • Python编码系列—Python建造者模式:构建复杂对象的优雅之道
  • C++学习笔记(22)
  • llvm后端之函数栈帧
  • Mastering openFrameworks_第五章_使用视频
  • 健身管理|基于java的健身管理系统小程序(源码+数据库+文档)
  • 清理.svn文件夹执行命令bat
  • -isystem isystem 实验记录
  • [译]CSS 居中(Center)方法大合集
  • AngularJS指令开发(1)——参数详解
  • Consul Config 使用Git做版本控制的实现
  • css属性的继承、初识值、计算值、当前值、应用值
  • HTML-表单
  • JAVA SE 6 GC调优笔记
  • JavaScript学习总结——原型
  • leetcode386. Lexicographical Numbers
  • Mac转Windows的拯救指南
  • MySQL的数据类型
  • STAR法则
  • Vue 动态创建 component
  • 搞机器学习要哪些技能
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 用jQuery怎么做到前后端分离
  • Linux权限管理(week1_day5)--技术流ken
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #每日一题合集#牛客JZ23-JZ33
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (WSI分类)WSI分类文献小综述 2024
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (六)vue-router+UI组件库
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .net core 使用js,.net core 使用javascript,在.net core项目中怎么使用javascript
  • .net mvc 获取url中controller和action
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET设计模式(11):组合模式(Composite Pattern)
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • /etc/motd and /etc/issue
  • [8481302]博弈论 斯坦福game theory stanford week 1