前端早早聊大会-与掘金联合举办-全年学习

别针.001.jpeg

一、个人简介

大家好,我是来自天猫精灵 IOT 前端团队的别针,很荣幸今天有机会跟大家分享我们在物联网领域一些跨端开发的实践经验,我是 2010 年开始从事前端开发的工作,先后在携程、点评、艺龙等公司呆过,17 年底加入阿里,一直从事 IOT 前端方面的工作。

二、目录

别针.002.jpeg

这是本次分析的大纲,接下来会按照这个顺序来介绍下我们在 IOT 场景下的跨端思考和一些关键技术点。

三、跨端场景和特点

别针.003.jpeg

首先介绍下跨端场景特点

1.跨端场景

别针.004.jpeg

提到物联网,大家可能首先会想到各种各样的设备,我们的跨端场景就是需要跑在各种各样的设备上,所以这个跟之前大家分享的,主要是在手机端可能会有一些差异。

目前我们主要兼容的设备包括端(物联网设备):手机、音箱、电视、手表和车机… 未来随着我们的设备增多,还会有新的设备需要去兼容。

这些设备主要涉及到系统主要有:iOS、Android、Linux、RTOS…

这些设备涉及到的技术栈就是 ReactNative、H5、cube 小程序。可能 cube 这个东西大家会比较陌生,在物联网场景下相当于是小程序与 rn 的一个结合,它相当于是开发的时候,DSL 是小程序,但是渲染的时候是通过 cube(C/C++)去做视图的渲染,把我们的跨端场景总结下来,有这么一些特点,碎片化特别严重,我们涉及到的端、屏、技术栈非常多,而且还在持续增长。

2.跨端特点

别针.005.jpeg

我们应用特点就是强交互、功能种类多、设备多的特点,它的业务场景是不一样的,我们在不同设备领域去做技术沉淀周期比较长,所以我们需要对我们的应用,从一个比较长的时间线去看我们应用的发展。

3.应用展示

别针.006.jpeg

这边展示的是目前我们线上跑着的一些 IOT 的应用,在其它屏上那些应用暂时还没有对外开放,这里暂时只展示了手机端的一些应用。

四、跨端方案和思考

别针.007.jpeg

因为碎片化严重,我们主要解决就是怎么提效的问题,不然的话这一块肯定是一个人力投入的黑洞。

1.如何降本提效?

别针.008.jpeg

针对我们的场景,我们找到了两种比较有效的提效方式:

  • 跨端开发方案:主要解决技术栈碎片的问题。
  • 可视化搭建:主要解决平碎片功能以及 UI 碎片的问题。

因为今天是跨端的专场,这里会介绍跨端方向的一些问题。

2.跨端的实现方式有哪些?

别针.009.jpeg

2.1 代码编译
  • 目前业界比较流行,大多数框架所采用的一种方式;
  • 实现原理:将一种 DSL 通过编译的方式编译成各个平台的 DSL,结合一些运行时的支撑框架,然后实现跨端。

2.2 跨平台解析器
  • 是定义一套 DSL,在各个操作系统上实现这种 DSL 的一个解析引擎,以实现跨端。最出名的比如说 Web 以及 Flutter。

2.3 云端渲染用户端展示
  • 在云端进行渲染,客户端只是作为展示,借着网速的提升,以及云时代跟 5G 时代的到来,采用的一种方案,目前业界主要在一些手机游戏上有过一些相关的实践。

3.百分百的跨端是否可行?

别针.010.jpeg

我们做跨端,其实最终的梦想是希望能够达到一次写代码在各个端能够完全一样的去运行,但是这种方案是否可行,我们来分析一下。

3.1 代码编译方案:
  • 做过代码编译的同学应该都知道,不同语言之间语法能力上本身是不对等的,想要通过编译的方式来达到百分百的跨端,基本上是难度非常高,基本上是不可行的。

3.2 跨平台解析器:
  • 如果不考虑性能资源占用和成本的问题,这种方案是很有希望做到百分百实现跨端的。但比较可惜的是除去我们现在标准操作系统之外,其实现在还有一些超级端,这些超级端它承载了一些操作系统的角色,但是里面并没有提供操作系统这样的一个完整的开发能力,比如说现在最流行的小程序,这其实是一种受限环境。在这种受限环境下,这些解解析器可能就很难去百分百去实现它的能力。

3.3 云端渲染
  • 这种方案理理论上是一种比较完美的扩大方案,因为你运行时是在云端,我们是可以完全采用一样的技术栈,渲染出来之后下发到设备端进行展示,但是受限于目前就是 5G 的普及,以及一些环境因素,现阶段只能进行一些探索和展望。

4.现实一点,我们应该选择哪种跨端方案?

别针.011.jpeg

通过刚才的分析,我们选择的是第一种就是代码编译的方式

5.选择哪种 DSL 作为开发态 DSL?

别针.012.jpeg

5.1 怎么选择?
  • 根据团队情况,以及你们主要投放的哪些端,以及团队成员的技术背景来去具体分析采用哪种。

5.2 我们的选择
  • 我们团队主要的技术站其实是 React 技术栈,我们投放最大的端其实是小程序。天猫精灵 APP 以及天猫精灵音箱里面都集成了支付宝小程序的容器,所以小程序是我们投放的最大的一个端。为了共享小程序的生态,同时我们对三方去开放的一个开发体系,也是小程序的开发体系。
  • 我们的方案:React 以及小程序的双 DSL 开发方式。

6.如何实现跨端的最大化复用?

别针.013.jpeg

确定了 DSL 之后,我们来看怎么样实现跨端,我们按照应用各个部分的技术职责对它进行了拆分,可以拆分成 API、基础组件、模板、布局、样式、动画、组件模型、应用模型等。

7.如何摆脱历史包袱,对跨端方案进行持续升级?

别针.014.jpeg

当我们要开发的应用,它的生命周期比较长的时候,长过一些技术战的迭代的时候,我们就要考虑怎么使我们的应用能够跟随技术栈的升级去不断的更新我们的技术栈,而不是绑死在一个框架上。

这也是我们在做技术选型设计的时候重点考虑的一个点。我们是安装应用它的功能进行不同维度的模块划分,拆分的粒度需要根据应用的特点来看。比如说,现在流行的微应用,主要是采用子应用的粒度拆分,还有一种拆分方案比如说按照页面维度或者按照模块的维度去拆分。

8.我们的跨端架构方案

别针.015.jpeg

这张图简单展示了我们对模块管理的简单示意,我们开发了一个模块管理的系统,去管理我们源代码编译出来各个平台上代码的模块。

五、关键技术点

别针.016.jpeg

1.跨端基础组件

别针.017.jpeg

基础组件是你开发应用视图层不可分割的一个最小的组件,组件基本都是有平台本身提供的。对于基础组件来说,我们主要的工作其实就是抹平各个端各个平台上的基础组件的差异。

基础组件按照它的功能特点来说,其实可以分为两大类,一类是布局组件,一类是功能组件。

1、布局组件
  • 常用布局组件:View、Text;
  • 我们可以通过编译的方式,去把大量不同的布局组件编译为 view 跟 text 两种组件,然后结合他们的一些默认样式实现 HTML 里面比较丰富的有语义化的一些标签。

2、功能组件
  • 常用功能组件:Image、Video、Input、Canvas、Map……
  • 这些组件是每一个组件有一些特殊功能,现在对比下来各个平台上提供的这些功能组件都差不多,主要区别在于功能组件的名称,它的属性上的一些差异,对于这些组件我们主要做的事情就是去对比各个平台上组件的差异,去对他们进行抹平。

2.跨端模板

别针.018.jpeg

基础组件是组成模板的原料,对于模板来说其实也是目前通过编译方式去做跨端里面主要编译工作之一,目前主要编译模板分以下两类:

2.1 指令模板
  • 指令模板就是在类似于 xml 的基础上去定义了一套指令,比如说属性或者标签之类的来实现有限的逻辑能力,比如说简单的表达式,循环判断,像 Vue、小程序其实都属于这类模板。

2.2 JS 语言混合模板

别针.019.jpeg

JS 语言混合模板,就是在字符串或者 xml 中使用特殊的字符进行分割,把 JS 语法混入进去,使模板具有 JS 几乎完整的表达能力,JSX 就属于这类模板。

2.3 两个模板比较
  • 单从模板层面来看,语言混合模板的表达能力肯定是要远远大于指令模板的,但是通过模板与数据结合渲染出的结果上来讲,其实两者的能力是对等的。
  • 模板结合数据渲染出的结果,两个模板几乎可以把它们等同,而指令模板的表达能力,因为是 JS 语言混合模板的一个子集,JS 混合模板就相当于是指令模板,再加上一些额外的 JS 逻辑达成等式。
  • 语言混合模板,对数据渲染就等同于指令模板,再加上通过一个额外的 JS 逻辑,对于要渲染的数据进行预处理,然后去渲染,根据这个等式,就可以通过编译的方式对模板进行编译。

别针.020.jpeg

因为编译的方式其实是很开放的,对于两种模板互转的方式,这里介绍一下我们通过提出冒泡的方式,将一个语言混合模板,把它分离成一个指令模板以及一个预处理函数,如下图所示:

别针.021.jpeg

这张图其实就是一个简单的示意,就是我们怎么通过编译的方式,把一个 JSX 的模板编译成一个指令模板跟一个预处理函数,为了显示上的简介,我们省略了很多中间节点,只把一些关键节点保留下来。babel 在节点树上遍历,其实是通过深度遍历的每个节点,又分为进入和离开两个时机对节节点进行操作。

我们通过冒泡的方式对模板进行分离的时候,会配置我们要编译的目标指令模板,支持哪些语法,这样的话在进行分离的时候,可以把支持的语法分离成指定模板,不支持语法分离到处理函数里。具体的过程就是我们在根节点进入的时候,会在根节点的 state 上挂三个栈,一个是作用域栈,一个是支持的语法栈以及不支持的语法栈

然后下面每个节点,我们在它退出的时候会去判断,看看当前节点以及它的父节点,是不是都是我们所支持的语法或者不支持的语法。如果跟它的父节点类型是一样的,那么就继续遍历。当我们遍历到一个节点,比如说当前节点它是我们支持的语法,而它的父节点是我们不支持的语法,或者就是当前节点是我们不支持语法,父节点是我们支持的语法的时候,我们就会把当前这个节点 push 到根节点创建的栈上,从另外一个栈上再弹出我们父节点同类的节点挂载到父节点上,依次进行冒泡。这样的话我们通过这种冒泡的方式,一直遍历完之后,我们就把整个节点树分离成了一棵是我们指定模板所支持的语法节点树,一颗树是我们不支持的语法节点树,不支持的语法节点树其实就是我们分离出来的数据与处理函数。

这里介绍的只是核心的处理过程,其中还有更多其它细节操作,比如说本身不同的指令,模板语法具体的语法细节是不一样的。就像刚才 uni-app 他们介绍的时候,其实也对比了不同的模板语法里面的一些差异,其实里面对于支持的语法节点也还要进行一次转换。

3.跨端样式

别针.022.jpeg

样式跨端主要分为这 3 个主要层次的能力:

3.1 基本样式能力对齐
  • 比如说 RN、小程序或者 H5 里面,同样的样式表,上面样式的语法,名称之类的,会有一些差异。

3.2 基本样式能力补齐
  • 不同的平台上,可能某些样式有缺失,但是我们可以通过比如说原生能力或者 JS 能力或者其它默认样式的转换来能够补齐这方面的能力。

3.3 样式继承、选择器等高级功能
  • 我们所采用的方式是基本能力对齐以及样式补齐上的一部分,然后我们没有选择样式这一块继续使用继承跟选择器的功能;
  • 之前我们在 RN 里面有实践过,让样式去支持类似样式继承、选择器这样的能力,但是因为这样的方式会造成组件节点上的 style 会数量暴增,并且没法通过 StyleSheet 方式对这种数据传递做压缩,所以造成本身通道数据传输量暴增,性能会有明显的下降,所以我们放弃了这种。在我们这里主要就是对于基本的样式进行了抹平,然后采用非选择器非继承的方式来处理样式,

4.跨端组件模型

别针.023.jpeg

在组件模型以及应用模型方面,这一块主要就是在以下几个方面各个平台上有差异。

  • 生命周期;
  • 数据到视图的渲染方式;
  • 视图事件的监听方式;
  • 组件引用方式。

这一块刚才宝哥介绍 uni-app 的时候也有一些介绍,这里面其实就是一些细节的处理,这一块涉及编译的不多,是为了支撑运行时能够抹平做的一些简单的提取编译,然后大部分功能其实都是在运行时去实现的,这一块就不做详细介绍。目前一些开源的跨端框架,这一块其实都有实现,如果有兴趣的同学可以找一些开源框架去看一下这一块的实现。

5.跨端应用模型

别针.024.jpeg

应用模型也比较类似,只不过要抹平的点有些差异。因为我们之前重点介绍了,其实我们为了不强制捆绑在一种框架上,让我们的应用能够随着我们的发展,能够持续跟随技术的迭代,所以我们不同的模块可能采用不同的技术方案去实现跨端,那其实这里面就考验我们通过什么样的方式去进行源代码的组织

6.源代码组织方式

别针.025.jpeg

根据项目的大小可以有不用的管理方式。

6.1 中小型项目

对于中小型项目的话,其实可以使用 yarn workspace 或者 lerna 进行这种代码管理,它其实都是在同一个代码仓库里,通过文件夹的方式去划分不同的模块,每个模块其实可以有自己的脚手架、有自己的文件依赖,可以发布独立的 npm 包,把所有的模块放在一个个的仓库,对于中小型项目这种方式其实足够管理了。

6.2 大型项目
  • 特点:后续模块数量增长的会非常大,以及它的时间会延续的比较长;
  • 组织方式:采取类似于 git group 的方式进行管理,就是每个模块是一个独立的 git 仓库。

六、总结

别针.026.jpeg

没有好的方案,只有最适合的方案

别针.027.jpeg

要根据我们的业务场景,各个方面的特点来考虑。比如说你要跨哪些端,这个就要考虑到这些端的技术栈有哪些?然后按照技术栈进行各个划分,看怎么样去抹平,然后以哪个端为主,首先要保证端上的体验,这个就会影响到你选用哪种 DSL 作为开发态的 DSL,你的一些技术倾向可能都要往端上有一些倾斜,还有各端的能力是否完全一致,就涉及到整套方案是写一次到处运行还是学习一次到处去用相同的方式去开发,以及根据项目团队的一些背景特点,选择不同的技术方案。

七、团队介绍

别针.028.jpeg

1.招聘要求

别针.029.jpeg

1.1 职责
  • 天猫精灵 APP 前端部分、天猫精灵小程序;
  • 天猫生活物联网平台的搭建;
  • 天猫精灵、音箱、手表、电视、车机等这些设备中的 IOT 部分前端工作。

1.2 现有技术方向
  • 多端多屏技术;
  • 可视化搭建;
  • 微前端;
  • AIOT 人机互动。

1.3 招聘职位
  • 高级前端工程师;
  • 前端技术专家。

2.加入我们

别针.030.jpeg

3.结束语

别针.031.jpeg


别忘了点下方送稻谷哈