其他
美团外卖终端容器无关化研发框架
总第480篇
2021年 第050篇
2019年9月,美团外卖技术团队联合多个研发部门正式推出了React2X,面向所有的前端研发人员,特别是按业务领域划分的团队,为大家提供一个完整的、开放的多终端容器无关化(Containerless)研发框架。
研发同学可以通过React2X框架快速创建、开发、构建、部署项目,在人力消耗最小的前提下,以期在不同终端上达到相对最佳的性能体验,并且能大幅降低因容器升级带来的替换和改造成本,让代码同构的复用率最大化。一、前言
二、目标与场景
2.1 核心目标
2.2 应用场景
三、挑战与优势
3.1 业界调研
3.2 技术挑战
3.3 项目优势
四、技术全景
4.1 底层基础框架
4.2 应用场景同构
4.3 落地场景与效果
五、展望与总结
作者简介
招聘信息
一、前言
面对美团内部丰富多样的技术容器体系(Mach、MRN、Titans、MTFlutter、MMP等),如何保证跨容器开发体验的一致性,以及建设跨容器应用开发的生态能力,是我们需要解决的问题。 公司内丰富的终端容器化技术蓬勃发展,而因业务升级带来的改造成本也比较大,亟待一款高扩展性设计的顶层框架作为技术抓手。 跨容器动态化能力覆盖,逐步成为各个业务方越来越重视的基础能力,可以大幅缩短需求交付的周期,提高上线发版的效率,并能有效地解决包体积大小的问题,提升业务的敏捷性。 多场景下的同构诉求,例如在各种推广页、模块化、游戏、轻量布局差异的PC/App同构场景下,可以节省多端研发的人力。
二、目标与场景
2.1 核心目标
解决公司内部多终端容器开发痛点:实现Webview容器、小程序容器、MRN容器、Mach容器、游戏容器、部分运营推广场景PC容器的代码同构复用,统一开发规范,抹平开发差异,并提供对其他容器的扩展能力。 建设跨容器动态化能力:跨容器动态化能力的缺失,导致产品不能够通过快速迭代来验证需求的效果,这个问题严重限制了业务的发展。跨容器动态化能力可以解决美团外卖业务端上发版和包体的问题,帮助业务实现快速发版上线、线上问题热修复、以及容灾的能力。 建设容器无关的开发生态体系:R2X最终要解决的是容器差异性,进行统一的技术生态能力建设,为多终端容器开发场景提升生产和运维效率。
2.2 应用场景
业务项目基于React语法为技术框架基础。 业务方有在多终端/多容器(包括MRN容器、Webview容器、MP容器、Flutter容器、Mach容器、PC浏览器容器)运行的需求。 业务方有特定的场景化诉求,包括推广页、模块化、小游戏、PC/App同构等等。
三、挑战与优势
3.1 业界调研
3.2 技术挑战
语法语义:MRN/小程序/Webview在DSL上就有着完全不同的语法语义。 端能力:同一容器在不同端上表现也存在不少差异,比如外卖App中MRN容器和美团App中MRN容器分别有定制的Native模块以及各类桥协议等。
首次成本:作为一个新定义的框架如何让新业务方快速上手,如何从存量业务线进行迁移。 边际成本:如何融合美团的基建生态,让业务方快速复用平台能力。
高可维护性、高度扩展性:如何快速升级、替换、新增一款底层容器。
3.3 项目优势
3.3.1 功能特点对比
3.3.2 性能数据对比
3.3.3 同构场景对比
四、技术全景
最下层是R2X的生态环境建设,在R2X内部去实现公司生态的常用SDK以及业务中的各项专题能力;并通过搭建物料市场/插件市场,以业务共建的形式丰富R2X生态。 再上层是R2XCore的根基,通过解析Command命令来执行唤起构建器,并实现了类似Webpack的插件系统,以插件化的形式组织驱动整个核心构建流程,便于维护以及扩展。 再往上是跨端容器层,它是整个跨端能力的核心,通过实现了不同的容器插件来将R2X代码编译成各端可执行代码,并通过运行时能力对组件/API进行对齐。 最上层是承载的App端,目前有美团外卖、大众点评、美团等多款移动App终端。 最右边是R2X在研发、发布、运维以及用户文档上做的一些建设。
4.1 底层基础框架
4.1.1 R2X-CLI的设计
整体流程冗长且复杂,长时间迭代会变得越来越难以维护。 每个容器的构建流程相互独立,且构建逻辑各不一致,有多处重复的逻辑处理。 编译流程缺少统一的关键节点,编译时无法进行业务方的定制扩展。
CLI结构变得清晰,只需要维护配置解析、插件解析等功能。 扩展性增强,可通过插件化的形式新增或删减容器/编译能力,保证代码独立维护功能的单一性。 编译流程可梳理,无论什么容器的编译流程都基于编译器暴露的时机执行并串联,整体流程清晰明了。
4.1.2 组件及API的设计
Webview标签采用的是XML写法,所提供的基础标签有<div/><a/>等等。 小程序采用的是WXML(WeiXin Markup Language)标签语言,也提供了一套完整的基础标签,但是和Webview有着较大的差异。 React Native则是采用的JSX(JS-XML)语法,虽然和XML很接近,但是又有着很多的不同点,同时它也有自己的一套基础组件,和Webview、小程序又截然不同。
接口差异:在不同端中都提供了相同或近似的功能,但是其实现方式以及调用参数可能存在着很大的差异,比如数据缓存Storage,小程序中用wx.setStorage/wx.setStorageSync,Webview则用localStorage.setItem,而MRN中AsyncStorage.setItem,几乎每一个功能点都有着多多少少的差异。 容器差异:各个端所提供的API都是各自的容器量身打造的,比如小程序的各业务接口类 API,完全是针对小程序所处的微信环境打造的,这类功能与其他端并不相关。 能力差异:各个端之间的差异我们可以通过定制的手段来适配,然而并不是所有的功能点在各个端上都能够实现。比如在Webview中就无法做到像小程序、React Native中提供很多原生能力,像是文件保存读取等等,这一类差异性在适配过程中都属于不可抗拒、不可抹平的差异。
@r2x/components
和基础API@r2x/r2x
。4.1.3 开放式插件能力
容器插件,用于封装R2X所支持的容器的核心编译能力。 功能插件,基于已有的容器插件,在此基础上进行某种特定功能的自定义实现。
小程序容器插件:@r2x/plugin-container-wxapp。 MRN容器插件:@r2x/plugin-container-mrn。 Titans容器插件:@r2x/plugin-container-h5。
4.1.4 特性能力-多态能力
多态组件/API,R2X根据文件后缀区分编译目标端。
差异化代码,R2X提供getEnv环境方法用于判断当前语句编译目标端类型。
4.2 应用场景同构
4.2.1 页面级容器场景同构
不能在包含JSX 元素的map循环中使用if表达式 ✅ 不能使用Array#map之外的方法操作JSX数组 ✅ 不能在JSX参数中使用匿名函数 ✅ 暂不支持在render()之外的方法定义JSX ✅ 不允许在JSX 参数(props)中传入JSX元素 ✅ 不能在JSX参数中使用对象展开符 ✅
4.2.2 模块级容器场景同构
核心驱动包,容器驱动的核心,针对渲染能力、解析能力、缓存能力、性能监控四个方面进行了实现,达到动态化驱动效果。 业务容器自定义,基于SDK提供的驱动能力,针对不同展位特性进行了容器自定义功能扩展配置,让业务方可根据实际业务场景自行扩展。 分环境构建,主要实现了将类React语法进行AST编译解析,根据构建平台分别编译成对应的Bundle产物。 自动化构建部署,将构建能力接入Talos(美团内部自研的构建部署工具),再结合低代码业务工具实现一键部署,将编译产物根据配置项上传至DD(美团内部自研移动端动态下发平台)。
4.2.3 PC/App适配同构
%%platform%%
,比如%%RN%%
表示React Native端独有,%%MICRO%%
表示PC微前端独有,%%MICRO|Webview%%
表示PC微前端、Webview 两端生效。示例代码如下:import B from '@r2x/r2x-b'; // %%MICRO%% 只在MICRO端保留。
import C from '@/utils/c'; // 这是所有端生效的公共模块。
import D from '@r2x/r2x-d'; // %%MICRO|Webview%%在MICRO、Webview多端生效的模块。
4.2.4 小游戏容器场景同构
渲染层的兼容:实现游戏引擎在多端环境下渲染能力的兼容(Canvas、WebGL)。 业务层的兼容:实现基础API、项目流程、公共模块的兼容,制定游戏差异的个性化定制规范。
4.3 落地场景与效果
R2X-推广页容器场景同构
R2X-模块化容器场景同构
R2X-小游戏容器场景同构
效果收益
五、展望与总结
开发体验优化,目前想接入或正在接入的兄弟部门已经越来越多,如何减少接入成本,丰富基础建设,优化开发体验,帮助大家快速迁移接入,将是下一阶段的重要课题。 渲染性能优化,在美团外卖场景下性能优化一直是我们在兼顾高效生产的另一个重要指标。特别在小程序场景下,低端机型的性能体验一直是业界瓶颈,如何突破这一难关将会是同构方案全面推广的“敲门砖”。
作者简介
阅读更多