首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >美团外卖前端容器化演进实践

美团外卖前端容器化演进实践

作者头像
美团技术团队
发布于 2019-12-04 03:13:35
发布于 2019-12-04 03:13:35
65100
代码可运行
举报
文章被收录于专栏:美团技术团队美团技术团队
运行总次数:0
代码可运行
提单页在美团外卖交易链路中非常重要,但随着业务不断发展,提单页模块越来越多,逻辑的耦合也越来越重。为了解决这一问题,需要实现提单页的动态化,而动态化是需要基于容器来实现,所以,美团外卖技术团队提出了提单页的容器化方案。希望本文对同样深受此问题困扰的同学有所帮助,有所启迪。

背景

提单页的位置

提单页是美团外卖交易链路中非常关键的一个页面。外卖下单的所有入口,包括首页商家列表、订单列表页再来一单、二级频道页的今日推荐等,最终都会进入提单页,在确认各项信息之后,点击提交订单按钮,完成最终下单操作。

所支撑的业务

虽然提单页的代码统一放在外卖代码仓库中,但根据业务发展的需要,提单页上的模块分别由不同的业务部门去负责维护。主要包括以下业务方:

外卖侧业务

  • 提单页绝大部分模块的需求开发和日常维护都是由外卖侧的研发同学在负责,包括地址模块、商家商品信息模块、折扣信息模块、准时宝、隐私号、发票备注等。

闪购侧业务

  • 当从商超等频道进入提单页时,提单页生成的是闪购侧订单,闪购侧的订单在配送方式、红包、下单路径上都与外卖订单有所区别,但又依赖于外卖的基础功能模块,因此与外卖侧功能存在严重的耦合问题。

其他业务

  • 提单页上的部分模块对动态化配置能力有着很高的要求,这些模块使用Mach等动态化模版来实现相关的业务逻辑,由专门的业务组负责开发和维护。

随着业务的不断迭代,提单页的模块也越来越多,逻辑的耦合也越来越重。现在提单页的UI展示模块已经超过30个,这些模块的展示与否基本上通过服务端的下发数据来决定。在不同的订单类型下,提单页所展示元素的差异越来越大,很多模块的代码已经不适合统一放在一起维护,代码拆分的需求十分强烈。此外,客户端包体积是衡量客户端性能的重要指标,为了解决业务发展带来的提单页代码量急剧增长的问题,同时实现页面元素的动态配置,我们希望能够实现提单页的动态化,而动态化需要基于容器来实现,所以我们提出了提单页的容器方案。

问题和挑战

提单页的容器化与外卖首页的动态化有以下几点不同:

  1. 提单页整体动态化的需求不是很强烈,并且API改造的成本比较高,因此API接口字段保持不变,需要在客户端层面去做转换。
  2. 首页模块基本仅作为展示用途,提单页模块的交互逻辑要复杂一些,比如发票模块,进入二级页面操作完成后还要更新提单页的数据。
  3. 首页模块的UI展示各模块之间是完全独立的,而提单页的模块是根据功能聚合在一个组,这些模块条件出现的位置不同,展示的样式也不一致,如下图备注发票模块所示,最上层和最底层的模块上都带有圆角,所以提单页需要外层再添加一个模块组。

容器化后的提单页,需要实现模块之间的互相无感知,根据服务端的下发数据,客户端可以将闪购代码仓库内的模块和外卖代码仓库内的模块拼接起来组成完整的提单页展示给用户。当用户在提单页完成一系列操作时,各模块可以提供必要的参数给服务端。要想实现这一点,我们需要考虑以下几个问题:

  • 模块注册问题,如何在无直接依赖的情况下,让提单页获取页面可用模块。
  • API数据分发问题,如何将服务端字段转换为模块可用数据,同时不侵入到模块这一层。
  • 通信问题,模块之间如何实现联动效果。
  • 页面更新和复用问题,在提单页刷新时如何提交数据给服务端以及如何完成模块的更新。

设计方案

1. 容器化整体的架构图设计

容器化是我们在外卖平台化之后对多方业务能力的支持和扩展,在不改变API数据源等前提下,我们保证其具有动态可配置化的能力。为了更好地支撑业务,我们在业务层面抽离出来容器化框架层,其所提供三个部分的核心功能: 1.功能节点扩展及通信功能;2.可配置化功能;3.数据分发功能。在最上层业务容器中,目前所支持外卖提单页面模块、闪购提单页模块、提单页Mach(外卖动态化模板)模块、提单页MRN(RN页面)模块四种不同的业务。

1.1 概念解释

在容器化框架设计过程中,我们引入了一些新的定义,比如在Android端引入了Block的概念,这里的Block是一个功能模块的简称。在提单页页面中,我们可以理解为一个Block对应一个功能条目。在iOS端有与之对应的概念Element(由于两者没有差异,下文陈述中用Block代指两者)。

Block有两种类型:其一是普通的Block,其包含BlockView(视图层)和BlockViewModel(数据层)。BlockView(视图层)用来展示具体的视图以及内部的业务逻辑;BlockViewModel(数据层),用来数据解析。其二是LogicBlock,是没有视图的Block,单纯地用来做数据业务处理。

1.2 整体概述

在容器化之前,我们的业务大多是模块化的结构,模块化宿主类是承载所有模块化的管理类,各个模块之间通过宿主类或者控制器进行数据交互。但在容器化改造中,我们将之前宿主类中管理的模块进行拆解,并重新定义了宿主类的职责。在容器化宿主类中,我们将不再持有各个功能模块的引用,而只要持有Root Block这一个实例,就可以完成对所有功能模块的管理。而Root Block Context则用来处理父Block与子Block之间的通信以及子Block之间的通信。

1.3 核心功能

第一部分功能节点扩展及通信功能。主要是目前页面的集成和通信关系,其中Root Block是Block Tree的根节点,下面会挂载一些SubBlock子节点,Root Block会控制整体的数据流的分发以及整体样式;Root Block Context可以理解为上下文环境或通信的总线。每个模块都有自己的Context,来维护自己向外部提供数据以及业务逻辑的能力,这些子Context会统一注册到Root Context中进行管理维护。

第二部分可配置化功能。在发起数据请求成功之后,客户端根据注册的Key以及接收到的数据,动态创建Block的容器化能力。遍历解析数据以及配置文件,先动态创建viewModel,将创建好的viewModel绑定到生成的Block模块上,动态添加到Root Block中。多业务方在完全不用相互感知的情况下,完成对新增模块的开发。

第三部分数据分发。既将解析之后的数据,由Root Block节点进行数据分发到各个子Block,各子Block的BlockViewModel在更新数据之后并回传到Block中,Block用更新后的数据更新View的展示。其中,数据可以自动完成分发,也可以手动的接管数据流进行相应的处理。

2. Block注册问题

2.1 Android 注册的设计方案

Android 是在编译时期,通过APT(注解处理器)的方式,将在指定模块上的注解信息和Block类关联起来,生成Block类对应的工厂类,然后将这些工厂类存在全局的Map集合中,并在运行时进行初始化操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@DynamicBinder(nativeId = "block_key_d", viewModel = blockDViewModel.class, modelType = blockDInfo.class)

NativeID是用来标识Block块的唯一Key,viewModel是用来绑定View视图的数据层, modelType对应着API的数据Model。

2.2 iOS 注册的设计方案

iOS使用Kylin注册,Kylin是美团平台开发的基建库,利用Clang提供的section()函数,在编译时Kylin将{kylin_Key,kylin_Data}格式的数据写入到可执行文件的特定数据段中,运行期就可以通过读取指定的Key值获取相应的数据。使用这种方式,注册代码分散在每个组件内部。注册内容:组件native_id、Element名称、viewModel,其含义同上。

注册宏:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define PGA_ELEMENT_REGISTER(NATIVE_ID, PGA_ELEMENT, PGA_VIEW_MODEL)  \
    KLN_STRING_EXPORT("AppKey_"#NATIVE_ID"", "{ \""#PGA_VIEW_MODEL"\" : \""#PGA_ELEMENT"\"}");

3. API数据结构化

由于API下发数据的不规范性,需要将数据按照data_key这种数据模式的方式进行整理,然后在获取数据之后,按照规则进行数据解析并创建相应的功能Block。

目前API数据返回的格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "data":{
        "xxx_pay_by_friend": true,
        "xxx_by_friend_tip": "发给微信好友,让TA买单",
        "xxx_by_friend_bubble_desc": "找微信好友买单",
        "xxx_friend_order": false
  }
  "code":0,
  "msg":""
}

由于这种格式是平铺分散的,没有将特定功能点的字段聚合在一起表示,不利于我们动态地将数据Model与Block绑定在一起。

需要我们将一个模块的数据统一在一个JSON对象中,整理之后API数据返回的格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "data":{
       "pay_by_friend":{//key
          "xxx_pay_by_friend": true,
          "xxx_by_friend_tip": "发给微信朋友,让TA买单",
          "xxx_by_friend_bubble_desc": "找微信好友买单",
          "xxx_friend_order": false
       }
  }
  "code":0,
  "msg":""
}

将平铺的API数据整理成定制的结构化数据,将Key作为唯一的标识,那么就可以方便地用来对应指定模块化Block中所需的数据Model。

布局及位置信息会对应相应的模块视图层,这由另外的layoutInfo字段给出。数组中的每条元素对应每一个Block模块 , 其中 native_id的值是唯一的且与上面Block在注册时候的Key保持一致,data_key的值映射上面整理之后的API数据的Key,这样在编译时期生成Block的时候,就可以动态地关联相应的ViewModel以及数据模型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "layout_info":[
      {"native_id":"order_pay_by_friend","data_key":"pay_by_friend"},
      {
        "native_id":"block_container_default",//容器组
        "children":[
          {"native_id":"order_flower_cake","data_key":"flower_cake"}
        ]
      }
    ]
}

当然,这里可以以组为维度将一些功能相似的模块聚合在一起,native_id的含义同上,Children是子Block结点的数组。

4. 模块间通信问题

由于之前模块化的时候,我们通过中间类的方式承载各个业务模块的通信逻辑。以Android为例,我们将多个子模块之间需要通信的逻辑,用接口的方式抛到Activity层,由Activity层进行业务逻辑的实现,但是由于子模块众多,最终导致该类的膨胀和模块的高耦合性,难以进行扩展和维护。

在容器化设计的时候,为了更好地使各个业务之间进行通信,降低耦合性,我们引入了BlockContext,同上所述,理解为通信总线。

每个Block都有自己的BlockContext,各个BlockContext汇总到Root Block Context中去实现,最终,各个Block就可以通过BlockContext进行数据传递。

整体的通信分发图如下:

图中展示的两种数据方式

4.1 Command数据交互方式

将所需要的数据包装成事件,在指定的位置驱动事件的执行进而拿到需要的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//声明事件容器
private SupplierCommand<Object> mSupplierCommand = new SupplierCommand<>();
@Override
public SupplierCommand<Object> getSupplierCommand() {
    return mSupplierCommand;
}
//注册实现
context().getSupplierCommand().registerCommand(new Supplier() {
   @Override
    public Object run() {  
    }
});
//获取相应的Object对象
context().getSupplierCommand().execute();
4.2 Event数据交互方式

利用观察者的方式,订阅相应的事件,通过主动触发,从而完成数据分发等不同操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//声明事件容器
private SupplierEvent mSupplierEvent = new SupplierEvent();
@Override
public SupplierEvent supplierResponseEvent() {
  return mSupplierEvent;
}       
//实现订阅
context().supplierResponseEvent().subscribe(new Action() {
   @Override
   public void action() {
   }
});
//触发相应的操作
context().supplierResponseEvent().trigger();

5. Block页面数据分发问题

5.1 数据分发问题

Root Block在接收数据的之后,会按照Block结点进行数据的分发。父Block将数据逐次的分发给子Block。

Block Tree数据分发逻辑简介图

Block页面的刷新流程时序图

5.2 Block创建的顺序

Block创建的顺序由API结构化数据中的layoutInfo数组来决定,layoutInfo数组的具体格式如第三节API数据结构化中内容所示。容器化后的提单页会根据layoutInfo数组的顺序,依次创建对应native_id的Block模块。因此,对于一些基础公共模块(比如wm_confirm_order_logical对应的Block),我们可以将其放在layoutInfo数组的最前面让其提前加载,保证负责UI展示的Block创建时数据可用。

5.3 数据拉取问题

由于提单页的模块比较多,在页面曝光、页面刷新或提交请求时,需要从指定的模块获取相应的数据,作为请求的入参,那么如何做成在不感知其他业务方模块的情况下,完成数据的组装呢?

如上面的通信设计思路,我们利用Event数据交互方式,从各个模块中将需要的数据取出来,完成数据的拼装。其中不同业务场景提取数据需要的校验工作,也分散在各个模块中进行处理。最终,即使在物理层面上隔离了对Block的感知,但是依然可以完成对请求所需数据的获取。

6. Block页面的复用问题

在实际的开发中,有些Block的页面View大致上相似,但是逻辑上有些细微的差异,为了快速开发,我们在设计上复用了其视图。Block、BlockView以及ViewModel的关系:一个Block对应一个ViewModel和一个BlockView,一个ViewModel和一个BlockView可以对应多个Block。

计算机界有一句名言:“计算机科学领域的任何问题都可以通过增加一个中间层来解决。”(原始版本出自计算机科学家David Wheeler)相似的,为了视图层的复用,屏蔽数据层的差异,我们在数据层的逻辑中转部分引入一个中间层ViewData,ViewData是为了更好地适配数据模型以及区别视图展示上的差异,这样就大大提高了代码的复用率。

收益

在开发过程中,我们将iOS和Android系统的模块进行了对齐和统一,容器化完成之后,两端同一NativeID对应的模块展示着相同的UI数据,也具有完全一样的业务逻辑。经过容器化后的提单页,相关代码被划分到了33个模块当中,这些模块分别承担着不同的职责。这里按照模块的业务功能、所采用的技术栈和所属业务线将这些容器化后的模块进行划分,得到如下的柱状直方图:

容器化之后的提单页完全由各模块组成,这些模块可以负责UI展示,也可以不展示任何UI模块,单纯地处理业务逻辑。模块内部的开发方案也可以根据业务形态自由选择,相互之间做到了完全无感知。这些优点为后续提单页的业务迭代和技术优化都提供了很大的空间。

解耦的收益

开发效率提升

容器化之前的提单页,页面各部分共享同一个数据模型,服务端接口数据返回后,在提单页控制器内进行数据的更新、过滤和二次加工之后,再分发给页面上的各模块。当不同的RD同时开发提单页的需求时,这些放置在一起的业务逻辑会提高RD的开发成本,另外很容易出现代码层面的冲突,在需要RD手动解决的同时,也很容易因为开发流程的不规范出现Bug。

容器化之后的提单页,开发模式也相应发生了改变,RD在开发过程中,不会感知到别的模块内业务需求的改动,各业务可以在各自的容器内进行有效的推进迭代,而不用担心会影响到其他业务,从而让多人协作开发效率得到一定的提升。

控制器瘦身

在客户端业务开发的层面,MVC架构得到了广泛应用。容器化重构之前的提单页,虽然也以模块化思想为基础做过多次重构,但是依然深受MVC思想的影响,在提单页控制器内保留了大量业务逻辑的代码。这些业务逻辑的代码最终会在业务迭代过程中逐渐变得臃肿和不可控,最终成为下一次代码重构计划中的业务背景。

本次提单页的容器化改造彻底解决了这一问题。基于PGA框架,包括接口异常处理、数据模型传递和二级页面跳转等业务逻辑代码都被收入到对应的Element和Block中,改造后的提单页中已经不存在业务逻辑相关的代码,彻底杜绝再次出现臃肿页面VC的可能。经统计,iOS侧提单页控制器的代码行数从2894行减少到289行,控制器类中仅包含Block组装的业务逻辑。

包体积减少

提单页承载着美团的外卖业务和闪购业务,在未进行容器化之前,两个业务方需要同时向订单库提交代码,在订单库整体“瘦身”的过程中,我们发现这种开发模式让包大小优化的工作多次出现反复,并且统计指标也难以统一和对齐。对提单页进行容器化改造之后,外卖和闪购分别维护各自模块内的代码,相互之间无依赖,闪购侧可以直接在自己的代码仓库内完成提单页模块的新增和修改,不需要再给外卖代码仓库提PR,也就不会对外卖侧的包大小统计产生影响。

动态化的收益

动态化是整个外卖业务的发展方向。提单页的动态化建立在容器化的基础之上,在完成容器化之后,就具备了动态化的基础。当前提单页的动态化,所指的主要是模块层级的动态化,提单页的各模块展示顺序、展示与否,都可以完全由根据服务端下发的数据决定,各模块可以自由地进行组合、拼装,实现提单页的动态配置。

两端对齐的收益

之前因为历史原因,提单页很多的功能模块,Android和iOS在实现上大相径庭,完全不一样的实现让两端在新业务需求到来时,在与服务端接口对接、开发工时和开发方案上都存在很大的差异,这些差异点对产品需求的排期、开发和测试上线上都产生了很多负面的影响。

提单页在容器化后的另外一项收益,就是Android和iOS在模块层级的代码实现,完成了统一。借助于PGA框架和Element注册机制,Android和iOS具有大致相同的模块结构,相同native_id的模块获取的API接口返回字段完全一致;在页面请求接口数据时,相同ID的模块也提供同样的数据字段。在后续的开发过程中,两端对API接口字段的请求趋于一致,可以最大程度地减少因为两端不一致带来的合作方开发成本,也可以在一定程度上减轻下游的测试压力。

总结与展望

外卖客户端一直在推动核心页面的标准化,同时一直在探索尝试让核心页面也具备动态化能力。提单页作为下单路径上的核心页面,在PGA框架的基础上完成了容器化重构。至此,外卖首页、点菜页和提单页在页面这一层级都统一使用PGA框架实现。统一化和标准化之后,可以让编程风格趋于一致,代码结构在不同平台保持统一,在后续的需求开发中,可以有效减少因为两端实现不一致出现的隐性开发成本。

提单页在容器化之后,让区域动态化的技术演进更容易推进。模块之间的解耦让不同模块可以自由选择模块内使用的技术栈而不会对其他模块产生影响。对于提单页的部分模块,完全可以通过Mach或者RN等动态化方案来实现,通过区域动态化来进一步减少开发成本,提高业务需求的开发效率。

在提单页之后,客户端会继续推进订单状态页使用PGA框架实现容器化,让标准化框架对用户下单路径上的核心页面实现100%覆盖。同时积极在提单页的商家商品信息展示、放心吃、准时保等模块探索页面的部分区域动态化,进一步缩减包大小,提高开发效率。

附录

1. Mach (马赫) 是外卖终端组自研的多终端跨平台级的局部动态化技术。

2. MRN 是美团基于React-native 0.54.3进行的二次封装,抹平了两端上的差异,并且提供了一些基础库和组件库供业务开发同学使用。

3. Metrics 是美团平台团队和外卖团队,开发的新一代App性能采集、监控、统计平台。

4. Hertz(赫兹)是一个自动化的性能采集与监控SDK,可以在开发、测试、灰度、运维各阶段,采集性能指标、检测卡顿、测量页面加载时间,帮助开发者监控和定位性能问题。

作者简介

李肖、廷瑞、彦平、同同均为美团外卖团队工程师。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 美团技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React Native在美团外卖客户端的实践
美团研发团队基于React Native开源框架,并结合美团业务场景,定制化开发了一套动态化方案。本文主要分享该动态化方案在美团外卖业务场景中的实践,希望能给大家一些启发。
美团技术团队
2019/12/23
2.3K0
React Native在美团外卖客户端的实践
WMRouter:美团外卖Android开源路由框架
WMRouter是一款Android路由框架,基于组件化的设计思路,功能灵活,使用也比较简单。
美团技术团队
2019/04/04
1.4K0
WMRouter:美团外卖Android开源路由框架
微前端在美团外卖的实践
微前端是微服务理念在前端的应用。之前美美给大家介绍过微前端在美团HR系统和美团闪购的实践文章。
前端劝退师
2020/03/17
1.1K0
Flutter Web在美团外卖的实践
在多形态业务场景下,如何保障多端体验的一致性,是前端技术领域一个比较受关注的方向。美团外卖前端技术团队基于 Flutter Web 探索跨端(App\PC\H5)的解决方案,真正实现“Write Once & Run AnyWhere”。本文系该团队的实践经验总结,希望能对大家有所帮助或者启发。
美团技术团队
2021/03/30
2.4K0
Flutter Web在美团外卖的实践
美团外卖广告平台化的探索与实践
总第491篇 2022年 第008篇 随着美团外卖业务不断发展,外卖广告引擎团队在多个领域进行了工程上的探索和实践,目前已经取得了一些成果。我们计划通过连载的形式分享给大家,本文是《美团外卖广告工程实践》专题连载的第一篇。 本文针对业务提效的目标,介绍了美团外卖广告引擎在平台化过程中的一些思考和实践。我们围绕实际遇到的问题、思考过程以及具体的落地方案,从业务的标准化、技术框架、产研新流程的改造等三个方面进行展开,希望能为读者提供思路上的借鉴。 1 前言 2 现状分析 3 目标 4 整体设计 4.1 整体思
美团技术团队
2022/03/04
1.5K0
美团外卖Flutter动态化实践
动态化是 Flutter 无法避开的话题。本文从 Flutter 的特点讲起, 阐述了美团外卖团队在整个 Flutter 动态化上探索的心路历程,还有设计理念、核心原理以及业务应用的经验。本文的视角也不局限于框架本身,更多思考了在解决问题的过程中技术团队需要做的事情,希望能对大家有所启发和帮助。
美团技术团队
2020/06/29
2.6K1
美团外卖持续交付的前世今生
美团外卖自2013年创建以来,业务一直在高速发展,从早期单一的美食业务发展成为包含闪购、跑腿、闪付、营销、广告等在内的平台业务。每个业务团队虽然都有不同的业务形态,但是几乎都有相同的诉求:需求能不能尽快的上线?本文将从外卖的历史实践中,浅谈一个好的持续交付需要综合考虑哪些关键因素,希望对大家有所帮助或启发。
美团技术团队
2020/02/19
1.6K0
美团外卖持续交付的前世今生
美团外卖Android平台化的复用实践
美团外卖平台化复用主要是指多端代码复用,正如美团外卖iOS多端复用的推动、支撑与思考文章所述,多端包含有两层意思:其一是相同业务的多入口,指美团外卖业务需要在美团外卖App(下文简称外卖App)和美团App外卖频道(下文简称外卖频道)同时上线;其二是指平台上各个业务线,美团外卖不同业务线都依赖外卖基础服务,比如登陆、定位等。
美团技术团队
2019/04/04
1.2K0
美团外卖Android平台化的复用实践
自动化测试在美团外卖的实践与落地
总第535篇 | 2022年 第052篇 随着美团到家业务的发展,系统复杂度也在持续增长。测试用例数量近两年增长约一倍,单端数量超过1万2千条,而研发人员的工作从大部分时间在开发,转变成一半时间在开发、一半时间在模拟环境和自测。因此,引入自动化测试就显得十分有必要,本文介绍了美团外卖在自动化测试方向做的一些探索和实践,希望对从事相关领域工作的同学能够带来一些启发或帮助。 1. 项目背景 2. 项目目标 3. 方案选型 4. 实践和探索 4.1 问题和挑战 4.2 前置条件准备 4.3 用例录制与回放的数据
美团技术团队
2022/09/20
1.4K0
自动化测试在美团外卖的实践与落地
Bifrost微前端框架及其在美团闪购中的实践
美团闪购研发团队开发了一套微前端框架——Bifrost,可以更好的帮助研发团队解决单一业务向多元化业务发展的管理问题。该方案已在美团闪购实践过,希望我们的思路能够对大家有所启发。
美团技术团队
2020/01/02
1K0
美团外卖推荐智能流量分发的实践与探索
美团外卖推荐团队在推荐算法的长期落地实践中,针对外卖业务情境化特点对排序模型进行深入探索与优化。本文介绍了面向情境化建模的“情境细分+统一模型”建模思路,通过用户行为序列建模以及专家网络两个模块的优化,实现不同场景间对信息独有性的刻画和信息共性的相互传递,进而提升全部流量效率。
美团技术团队
2022/12/16
1.4K0
美团外卖推荐智能流量分发的实践与探索
美团外卖Android平台化架构演进实践
美团外卖自2013年创建以来,业务一直高速发展。目前美团外卖日完成订单量已突破1800万,成为美团点评最重要的业务之一。美团外卖的用户端入口,从单一的外卖独立App,拓展为外卖、美团、点评等多个App入口。美团外卖所承载的业务,也从单一的餐饮业务,发展到餐饮、超市、生鲜、果蔬、药品、鲜花、蛋糕、跑腿等十多个大品类业务。业务的快速发展对客户端架构不断提出新的挑战。 平台化背景 很早之前,外卖作为孵化中的项目只有美团外卖App(下文简称外卖App)一个入口,后来外卖作为一个子频道接入到美团App(下文简称外卖频
美团技术团队
2018/03/29
1.7K0
美团外卖Android平台化架构演进实践
Shield:支撑美团点评品类最丰富业务的移动端模块化框架开源了
引言 一直以来,如何能更高效地开发与维护页面是Android与iOS开发同学最主要的工作和最关心的问题。随着业务的不断发展,根据特定业务场景产生的定制化需求变得越来越多。单一页面往往需要根据不同业务、
美团技术团队
2018/03/13
1.6K0
Shield:支撑美团点评品类最丰富业务的移动端模块化框架开源了
iOS App冷启动治理:来自美团外卖的实践
冷启动时长是App性能的重要指标,作为用户体验的第一道“门”,直接决定着用户对App的第一印象。美团外卖iOS客户端从2013年11月开始,历经几十个版本的迭代开发,产品形态不断完善,业务功能日趋复杂;同时外卖App也已经由原来的独立业务App演进成为一个平台App,陆续接入了闪购、跑腿等其他新业务。因此,更多更复杂的工作需要在App冷启动的时候被完成,这给App的冷启动性能带来了挑战。对此,我们团队基于业务形态的变化和外卖App的特点,对冷启动进行了持续且有针对性的优化工作,目的就是为了呈现更加流畅的用户体验。
美团技术团队
2018/12/07
1.4K0
iOS App冷启动治理:来自美团外卖的实践
美团跨端一体化富文本管理技术实践
为了减少产品和前端开发人员之间的矛盾,不断降本提效,美团医药技术部构建了跨端一体化富文本管理平台Page-佩奇。本文系统介绍了该平台的定位、设计思路、实现原理以及取得的成效。希望这些实战经验与总结,能给大家带来一些启发或帮助。
美团技术团队
2021/12/02
6780
美团跨端一体化富文本管理技术实践
美团外卖智能陪伴型导购的探索与实践
相比于其他电商场景,外卖场景对于实时发现和反馈用户兴趣的能力有着更高的要求。近年来,美团外卖算法团队摸索出了一套适用于外卖场景的智能陪伴型导购架构和策略。这一举措已经取得了显著成效,本文将详细介绍外卖搜索技术团队搭建智能陪伴型导购时,所遇到的挑战以及解决思路,希望能对大家有所帮助或启发。
美团技术团队
2023/09/05
6700
美团外卖智能陪伴型导购的探索与实践
美团大众点评 Hybrid 化建设
导语 上周末,精神哥去参加了好友小青在北京办的T沙龙,探讨移动端热更新相关的话题。Bugly曾为大家介绍过不少腾讯内部的热更新的框架,正好这次看到了美团,去哪儿以及微博同学在应用热更新方面的实践,整理出来发给大家,本周整理的是美团大众点评的吴卓同学分享的分享的 美团 Hybrid 化建设,其他的内容也会在后面陆续放出。 Hybrid 是移动端热更新最常用的手段,限于 App Store 上架审核时间较长,美团大众点评也采取了该方案,欢迎来自美团大众点旅游业务 iOS 负责人吴卓分享《美团大众点评 酒旅方面
腾讯Bugly
2018/03/23
1.4K0
迈向Flutter深水区:美团外卖Web-App一体化架构实践
今年 1 月,一篇《让 Flutter 在鸿蒙系统上跑起来》的文章引起了社区的关注,为了解更多美团外卖的 Flutter 落地进展,近日,我们采访了美团外卖商家终端团队负责人陈航,他透露,美团外卖商家 App 的鸿蒙适配正在推进落地中,不仅如此,最近半年他们也在探索基于 Flutter Web 体系的 Web-App 一体化架构,这两个部分目前在业务上都有比较大的进展,相关的技术案例也将分别在 ArchSummit 全球架构师峰会(上海站)2021 和 GMTC 全球大前端技术大会(北京站) 2021 跟大家分享。
深度学习与Python
2021/03/30
1.5K0
美团外卖特征平台的建设与实践
随着美团外卖业务的发展,算法模型也在不断演进迭代中。本文从特征框架演进、特征生产、特征获取计算以及训练样本生成四个方面介绍了美团外卖特征平台在建设与实践中的思考和优化思路。
肉眼品世界
2021/03/09
8920
美团外卖特征平台的建设与实践
美团负重开启新十年
由于疫情影响和阿里饿了么和支付宝启动的新战略,且正值美团十周年,在这样复杂特殊的背景下,关于美团未来十年将如何发展成为了焦点。
庄帅
2020/04/02
6340
美团负重开启新十年
推荐阅读
相关推荐
React Native在美团外卖客户端的实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验