引言
对于Taro框架,相信大多数小程序开发者都是有一定了解的。借助Taro框架,开发者们可以使用React进行小程序的开发,并实现一套代码就能够适配到各端小程序。这种促使开发成本降低的能力使得Taro被各大小程序开发者所使用。使用Taro打包出来的小程序和原生相比是有一定区别的,GrowingIO小程序的原生SDK还不足以直接在Taro中使用,需要针对其框架的特别进行适配。这点在Taro2时期已经是实现完美适配的,但在Taro3之后,由于Taro团队对其整体架构的调整,使得之前的方式已经无法实现准确的无埋点,促使了本次探索。
背景
GrowingIO小程序SDK无埋点功能的实现有两个核心问题:
-
如何拦截到用户事件的触发方法
-
如何为节点生成一个唯一且稳定的标识符
只要能处理好这两个问题,那就能实现一个稳定小程序无埋点SDK。在Taro2中,框架在编译期和运行期有不同的工作内容。其中编译时主要是将 Taro 代码通过 Babel 转换成小程序的代码,如:JS、WXML、WXSS、JSON。在运行时Taro2提供了两个核心ApicreateApp,createComponent,分别用来创建小程序App和实现小程序页面的构建。
GrowingIO 小程序SDK通过重写createComponent方法实现了对页面中用户事件的拦截,拦截到方法后便能在事件触发的时候获取到触发节点信息和方法名,若节点存在id,则用id+方法名作为标识符,否则就直接使用方法名作为标识符。这里方法名获取上sdk并没有任何处理,因为在Taro2的编译期已经做好了这一系列的工作,它会将用户方法名完整的保留下来,并且对于匿名方法,箭头函数也会进行编号赋予合适的方法名。
但是在Taro3之后,Taro的整个核心发生了巨大的变化,不论是编译期还是运行期和之前都是不一样的。createApp和createComponent接口也不再提供,编译期也会对用户方法进行压缩,不在保留用户方法名也不会对匿名方法进行编号。这样就导致现有GrowingIO 小程序SDK无法在Taro3上实现无埋点能力。
问题分析
在面对Taro3的这种变化,GrowingIO之前也做过适配。在分析Taro3运行期的代码中发现,Taro3会为页面内所有节点分配一个相对稳定的id,并且节点上的所有事件监听方法都是页面实例中的eh方法。在此条件下之前的GrowingIO便是按照原生小程序SDK的处理方式拦截该eh方法,在用户事件触发的时候获取到节点上的id以生成唯一标识符。这种处理方式在一定程度上也是解决了无埋点SDK的两个核心问题。
不难想到,GrowingIO之前的处理方式上,是没办法做到获取一个稳定的节点标识符的。当页面中节点的顺序发生变化,或者动态的增删了部分节点,这时Taro3都会给节点分配一个新的id,这样的话那就无法提供一个稳定的标识符了,导致之前圈选定义的无埋点事件失效。
如果想处理掉已定义无埋点事件失效问题,那就必须能提供一个稳定的标识符。类比与在Taro2上的实现,如果也能在拦截到事件触发的时候获取到用户方法名,那就可以了。也就是说只要能把以下两个问题处理掉,便能实现这个目标了。
-
运行时SDK能拦截用户方法
-
能在生产环境将用户方法名保留下来
逐一攻破
获取用户方法
先看第一个问题,SDK如何获取到用户绑定的方法,并拦截它。分析下Taro3的源码,不难就能解决掉。
所有的页面配置都是通过createPageConfig方法返回的,每个page配置都会有一个eh,从这里下手便能获取到绑定的方法。可见taro-runtime源码中的 eventHandler,dispatchEvent方法。
// page配置中的eh即为该方法
export function eventHandler (event: MpEvent) {
if (event.currentTarget == null) {
ev