原作时间:2019~2021年
此次共享,腾讯内网 / 外网同步发布。
内部代码地址:https://git.code.oa.com/fatboyli/QBDF
外部代码地址:GitHub - ventureli/QBDF
两年前的一个混淆包(无源码):GitHub - ventureli/VLOCInterpreter
作者:腾讯fatboyli(李文强)
1.立项
大约在2017年的时候,QQ浏览器IPAD项目组还在北京,那时候AppStore上架还比较慢,我们项目组决定做自己的动态化框架,动态化框架的目标是:真正实现一次发版本,多次发布。
整个iPAD项目组对整个市场的动态化框架做了一次比较深入的研究(为期一周)当时团队的分工如下:如今小伙伴都以天各一方,怀念和大家一起战斗的日子。
项目组分工
最开始我们并没有信心完全从0开始做一个全新的动态化框架,我们的想法是从WEEX上进行更改和扩展,形成QB团队自己的动态化框架。这一决定其实浪费我大约1.5个月的时间。WEEX的核心问题非常严重。整个动态化框架的设计和实现工作最后交给我来实现。
2.第一版本架构
接到任务后,大约利用了2周左右的时间对WEEX的源码进行了了解,我们第一步对weex的整个一些UI层面的限制进行了修正。主要有如下几个方面:(当时版本的weex比较早,现在这些问题可能已经不存在了。)
1.不支持完全比例排版(比如子控件的高度是父控件的宽度的50%)
2.对旋转屏幕的支持
3.添加iOS的特有属性支持(比如对tableView的group的形势的支持)
4.修正BUG
上面的内容我就不展开说明了,这并不是本系列文章的重点,但是里面有非常多有意思的小trick。有兴趣的同学可以单独联系我。
以上主要是针对UI层面的。但是WEEX在逻辑层面有天生的短板,它和RN是完全一样,采用预先注册的形势进行和Native交互,这只能算作是跨平台,并不能算作完全能力的动态化,我猜想这也是苹果之所以没有对RN和WEEX动手的原因。比如我在WEEX要用的某个NATIVE写好的BUTTON,那么这个BUTTON在WEEX引擎初始化的时候用以下代码注册好。
[WeexSDKEngine registerModule:xxxx WithClass:XXX]
这就根本算不上动态化了,这也造成了WEEX还不能够进行打PATCH。
第一版本架构
3.第二版本架构
但是 等等,当时是有能够完全能力动态运行和打PATCH的框架的偶~ YES, JSPATCH!所以我当初想的是用WEEX处理UI层面的操作,用JSPATCH来做逻辑层面的引擎从而达到无限制的动态化能力。架构大约是这个样子。
第二版本的架构
这里面的核心问题是怎么WEEX的脚本里嵌入JS脚本,这个设计也是比较有意思的,我设计的几个宏字符串
_OBJC_JSP_REGISTERTARG_(注册参数)
_OBJC_JSP_JSCALL_START_(JSPATCH代码开始)
_OBJC_JSP_JSCALL_END_(JSPATCH代码结束)
_OBJC_JSP_JSCALL_RETURN_(输出变量)
通过这几个宏字符串可以完成JSPATCH代码内嵌到WEEX里。这几个宏定义我也不展开详细介绍了,大致的思路是JSPATCH运行的时候先通过全局替换的方案,把这些字符串替换为一个内置的方法,比如 XXX_CALL(1),这样,然后把每段JSPATCH代码编号,这样当运行到XXX_CALL 这个方法时候,就能知道要去取什么JSPATCH脚本了。同时_OBJC_JSP_REGISTERTARG_方法预先注入参数,_OBJC_JSP_JSCALL_RETURN_ 输出参数即可。此时的代码看起来是这个样子的。
WEEX桥接JSPATCH
3.第三版本架构
完成了以上的工作,我们第一个QBDF框架就实现了。但是在此基础上我重新做了一个扩展,基于以下的想法。
WEEX是JS,HTML也可以运行JS
WEEX的JS可以桥接JSPATCH,那么HTML应该也可以桥接JSPATCH
HTML的JSPATCH是需要做加密的,否则会暴露NATIVE逻辑
所以我重新设计了一个新的模块作为QBDF的补充,就是 HTML+JS+CSS +资源 打包成为ZIP作为WEBAPP,通过后台模块下发和维护,同时JS桥接JSPATCH代码实现WEBAPP能力无限制。
如上后第三版本的框架的架构图如下。
第三版本框架
4.第四版本架构
以上框架完成后,基本上已经完成我们最初的想法,确实是一个有动态化能力的框架,
Weex开源代码深度定制,UI动态化
可动态配置
可以调用几乎任意代码,无须注册
虽有学习成本,VUE和JS比较好学
未来只要解决bug即时更新开源代码就可以了
但是其实在这个过程中,发现了几个问题。我做了如下的考虑。
SPATCH和WEEX都是基于JAVASCRIPTCORE的,都是基于WEBTHREAD的。而我们浏览器里面有大量的WEBVIEW一旦代码写的不注意就回出现死锁,甚至有时候无法避免以至于不能打PATCH,这也是我们和其他APP比较特殊的地方。
QBDF不应该是这样一个修修补补的二流框架!
还没达到我自己的要求
所以最后我们重新设计了整个QBDF框架,从0开始写一个OC语言的解释器和虚拟机动态运行OC代码,一个完全基于编译原理层面的动态运行OC语言的解决方案。第四版本的家购入如下。
第四版本QBDF脚本
好了,本文到这里就结束了,我们的QBDF经历过很多版本的迭代。