3

京东小程序架构设计解析

 1 year ago
source link: https://jelly.jd.com/article/62aff11a626785018c3ed46b
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JELLY | 京东小程序架构设计解析

京东小程序架构设计解析
上传日期:2022.12.16
本篇文章主要针对京东小程序的设计架构做部分解析,以期从架构视角为大家展示一个新生的平台如何去面对及解决业务或设计上的问题,后续会继续不断给大家呈现更详细的设计要点

近年来伴随移动互联网头部流量聚集效应愈发明显,如何做好存量市场的精耕细作成为各大 App 的核心课题。对于京东小程序来说,一方面市场需要它降低接入门槛,并提供足够安全的方式确保第三方业务能够良好运行,另一方面也需要结合自身平台的优势能力,给予第三方业务更大的赋能,让业务方找到更多的场景结合点。

京东小程序定义

京东小程序早在2017年就开始入局,进行探索之路。早期我们主要从技术层面去考虑一些痛点,如果把原生和H5比作两个点,由两点向中间不断靠拢并最终相交的技术形态是我们一直探索的方向,也就是说,体验接近原生但开发接近H5开发门槛。React native可以看作是由原生点向H5点过度的技术方式,JSSDK以及渐进式增强技术可以看作是H5点向原生点过度的技术方式。基于此,继承H5的开发门槛、无限接近原生体验、同时不脱离京东app的平台管控即是我们对京东小程序最初的定义。

随着近年来移动互联网的飞速发展,二维码早已成为我们生活中不可或缺的一部分,无论是移动支付、乘坐地铁或是健康码,二维码作为线上线下的连接通道被打开,同时也在“新零售”、“无界零售”等领域的不断发展,标志着“场景融合”成为了各个行业开始发展的重心,同时我们也在探索如何更多的开放能力并赋能商家。而开放所面临的首要问题是安全,我们需要抵御外部安全攻击、也要防止内部敏感信息泄露,所以我们不仅仅要从流程上去做安全管控,也要从架构上去解决安全问题。

京东小程序设计架构

关于京东小程序设计的构思,首先考虑京东小程序需要一套类web的语法规范,包括模板标签、样式、逻辑处理等内容,借鉴react、vue等语法规范的优势特点,同时也对标业内其它平台对小程序的规范定义,我们定义了一套DSL语言,并对开发规范做了明确。

其次是设计视图与逻辑分离的双层运行架构方面。视图层只负责UI渲染,逻辑层负责逻辑处理,UI与逻辑之间建立数据通信通道,小数据量通信采用js bridge为通道,能基本满足性能要求;视图层运行在webview容器里,且页面是webview多开机制,逻辑层主要运行在javascript core的沙箱容器里,它是整个小程序的控制中心,一个控制中心对应多个页面抽象实例;安全是这种架构设计的优点之一,视图层完全隔离开,基于webView内核的攻击就没有可能,同时逻辑层在开发及运行过程中均可做安全规则设计(包括关键字屏蔽、模块化权限保护、内容扫描等),抵御了一定的安全攻击风险,其缺点就是牺牲了一定的性能,因为通信成本体现在javascript与native通信损耗上(也即是JSBinding的性能损耗);从整体架构设计角度,我们考虑的是性能与收益的彼此兼顾,牺牲一定的性能、但体验影响不大,而安全收益很大,我们认为这是值得的。如下图1

2750b7b3a9d05be5.png

图1.京东小程序运行架构

再次京东小程序使用原生热布局的技术。Android布局使用了Layout,iOS布局使用了storyboard,不管是哪种技术,都不支持热更新,都是固化到apk和ipa文件中的。不过这两种技术都支持动态创建组件,所以React Native率先推出了利用JSX描述组件的位置、尺寸以及其他属性,然后再根据这些属性通过js brdige桥梁动态创建本地组件的技术。而JSX只是一种语法糖而已,本质还是javascript和xml的扩展,所以我们由此可得出结论:由xml进行UI布局描述,js进行交互逻辑处理,即可实现动态生成原生组件,我们称之为原生热布局。这种技术里,UI布局描述文件和逻辑处理文件,都可以动态从网络上下载进行热更新。下图2中,京东小程序混合式组件1使用web组件做布局,原生组件被动态创建后会覆盖在web组件之上,原生组件的层级比web组件层级高,这种设计会引入两个问题,一个是出现层级错乱问题,一个是web与native的交互同步问题。关于层级错乱问题,这个可以通过同层渲染技术实现,即保持原生组件与web组件嵌套,具体实现,下面会简单提到。关于web与native的交互同步问题,这个问题,在有上下滑动的页面表现比较明显,即当手动滑动页面时,页面如果有原生的控件如输入框,会发现输入框的上线滑动相比页面有一定的延迟动画,这是因为,滑动的事件是在web页面发生的,而滑动事件再传导到原生控件,是通过JSBinding机制调用API实现的,这会产生一定的时间延迟成本,前面已经提到过JSBinding是有一定的性能损耗,这里便体现出来,这种性能损耗并不会对用户体验产生较明显的负面影响,所以在我们的可接受范围之内;京东小程序混合式组件2使用的是同层渲染技术,同层渲染正好规避了上面web组件与native组件分离方案的缺点,即不会再产生交互同步问题和层级错乱问题。同层渲染,顾名思义就是指通过一定的技术手段把原生组件直接渲染到 WebView 层级上,此时「原生组件层」已经不存在,原生组件此时已被直接挂载到 WebView 节点上。你可以像使用非原生组件一样去使用「同层渲染」的原生组件,比如使用 view、image 覆盖原生组件、使用 z-index 指定原生组件的层级、把原生组件放置在 scroll-view、swiper、movable-view 等容器内,通过 JXSS 设置原生组件的样式等等

3cd433442c83956d.png

图2. 京东小程序混合式组件

在IOS端,我们发现,当把一个 DOM 节点的 CSS 属性设置为 overflow: scroll (低版本需同时设置 -webkit-overflow-scrolling: touch)之后,WKWebView 会为其生成一个 WKChildScrollView,与 DOM 节点存在映射关系,这是一个原生的 UIScrollView 的子类,也就是说 WebView 里的滚动实际上是由真正的原生滚动组件来承载的(这是核心要点)。WKWebView 这么做主要是为了 iOS 上的 WebView 滚动有更流畅的体验。虽说 WKChildScrollView 也是原生组件,但 WebKit 内核已经处理了它与其他 DOM 节点之间的层级关系,因此我们尽管去设置样式而不必担心层级遮挡的问题。既然WKChildScrollView也是原生组件,那么我们把小程序所需要的原生组件直接挂载到该WKChildScrollView节点上作为其子节点即可,从而继承了WKChildScrollView的相关特性。

在android端,主要是通过添加插件的方式实现,浏览器上的pdf预览也是这种方式实现,这些主要是通过<embed />标签实现的。如下图3,我们在小程序video组件的模板里增加一个<embed />标签,在运行时webview会在内核生成webPlugin实例,并暴漏一个view层给到java端,java端绑定到自己画布的SurfaceTexture上,当video组件创建时,便通过JSAPI调用原生组件的SDK,然后去绘制video组件在SurfaceTexture上。

4978f8ddabeb9605.png

图3. Android端同层渲染实现过程

最后京东小程序对开放能力的设计。不同于openApi的开放形式对于安全问题的架构设计,京东小程序从端上进行开放,必须结合自身的特点做安全架构设计。首先敏感数据的开放需要做脱敏或加密处理,比如用户的手机号、收货地址、会员信息等。京东小程序在端上吐出的数据经过脱敏进行展示,或加密传输到开发者平台,再结合openApi的安全规则,进行解密并进行数据消费。其次在涉及用户隐私信息时,需要进行用户授权操作,比如获取用户昵称、图像、手机号、位置信息、通讯录、录音等功能时需要做授权操作。最后就是安全组件设计,京东小程序的开放能力大部分以API的形式提供,如获取用户手机号可以调用jd.getPhoneNumber,但是手机号是敏感信息,通过这种方式就需要对真实的手机号进行掩码处理,或加密处理。现在,我们改变思路,将手机号的接口挂接到button组件逻辑里,这样可以在视图层执行“获取手机号”的操作,同时也能直接显示,而开发者无法拿到手机号的数据(逻辑层与视图层隔离),只能结合openApi的形式从拿。如下图4是安全组件的设计,图5是手机号的获取流程

923db78f00cbfb37.png

图4.京东小程序安全组件

9a3f63e5f8eb763a.png

图5. 获取手机号

探索之路,未来可期

架构是关键,同时平衡设计!在不断实践中,我们也在不断发现新问题,调整新思路,优化设计方案。目前重点关注性能方面,如编译性能、包加载、UI渲染等,我们可优化虚拟Dom的diff算法以提高页面渲染,可通过分包、数据预拉取、更快的QUIC网络协议等提升包的加载速度、可使用worker的多线程机制实现复杂逻辑计算、小而快的quickjs减小引擎大小且提升执行性能等,甚至我们也会尝试其它渲染性能更好的引擎,如flutter渲染引擎。面对技术的可能性,进行更多的尝试和探索,探索之路,未来可期!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK