还记得当初小程序刚出来爆火的场景,依附于微信确实是给我们带来了极大的便利,有着微信的流量,用完即走,无需下载,随时使用,从17年到23年,小程序已经深入人心,吃喝玩乐你都可以找到小程序的身影,疫情期间各种码的场景也给小程序带来了巨大的流量
当然不只是微信小程序,各大平台都推出了自己的小程序,像支付宝小程序、百度小程序、抖音小程序等等,这些app都紧跟潮流,实现了自己的小程序框架,经过了五年多时间的发展,小程序的框架已经趋于稳定,对于前端开发来说,甚至出现了一批专门做小程序的开发者
在开发使用上,相信大家在看文档的同时,已经有了自己的认识,但是小程序具体的架构是怎样的?它的原理是什么?我们如何在自己的app上搭建一套小程序体系?
当然微信的webview的方式也能实现小程序同样的功能,但是和微信的webview相比,小程序运行速度更快,因为小程序是双线程模型,逻辑和渲染是分开的,不会相互阻塞
在浏览器环境中,我们都知道,js代码的执行会阻塞页面渲染,渲染和脚本执行是互斥的,长时间的脚本运营导致页面无响应,这也是为什么react要进行切片操作
小程序采用双线程将两者分开,渲染和逻辑独立,互不影响,这就是为什么上面提到的小程序要比正常的H5要快,当然要让用户感受到快,首要的就是渲染
目前比较通用的四种渲染技术分别是
首先如果采用webview的渲染我们也提到了,同一个线程阻塞导致性能问题,采用native的方式做渲染的话我们改动小程序代码还需要同微信客户端一起发包,显然是不可能的,既然两个都不行,那采用hybrid的方式呢?将两者结合,比如react native就采用了这种方式
那什么是hybrid呢?说白了就是一个app中既有native的内容,又有web的内容,原理是其中有一个UIWebView,里面嵌入了一些web页面,这些web页面可以跨平台使用,比如ios和安卓,做个通用的壳就可以了,你可以把微信类比成hybrid app,小程序就是一些H5,界面渲染走的是web层面的渲染,然后由端上提供大量的接口提供丰富的客户端原生能力,保证在web的体验上能够使用一些原生的能力,并且更新比较迅速
近期微信新增了一种渲染引擎,为什么要新增呢?主要原因是由于web发展了这么久,虽然渲染方面已经做的很好的,但是还是由于历史原因以及复杂的渲染流程,让它在app中的表现还是有一定的差异,毕竟js总是会阻塞页面渲染,所以skyline是一种新的渲染引擎,skyline创建了一条渲染线程来负责layout, composite 和渲染等任务,并在在端上划出一个独立的上下文,来运行之前webview承担的js任务、dom树创建等逻辑。使得js不在阻塞页面的渲染,并且很好的保证了兼容性
但是其中的一些特性并不是原生就有,还是需要端上做一些能力的开发和兼容,比如CSS的calc 函数,小程序的picker-view组件等等都需要去做适配,成本较高,但是这确实是以后的小程序发展方向,能够较好的提升小程序性能
目前如果没有特殊指定,小程序采用的还是hybrid方式
除了渲染要快,对于小程序来说,最重要的一点是安全,对于web来说,我可以跳转任意想要的页面,比如从自己的页面跳转到baidu,跳转到juejin,都是很随意的,没有任何的管控,但是对于小程序来说不能这样,如果没有约束要跳转的内容,体验会变得很糟糕
另一方面,如果通过js代码获取一些用户的敏感数据通过dom操作,那用户信息泄漏会将事情变的无法进行
所以基于这些情况,微信内部阻止了一些操作dom,跳转,动态脚本执行的接口,只提供了一些js的脚本执行器,所以小程序提供了一个沙箱环境,这个环境不能有浏览器相关操作,而对于客户端来说,本身微信app就有内置的js解释引擎,iOS下是内置的JavaScriptCore框架,在安卓则是用腾讯x5内核提供的JsCore环境,创建了独立的线程去执行js代码,这个线程中执行的都是相关的业务逻辑的代码,逻辑相关的内容都在这里处理,渲染相关的都在webview中处理,通过逻辑层去控制渲染层的展示,这就是小程序的双线程模型
既然是双线程,那问题来了,线程之间的通信是有延迟的,就导致线程之间的通信实际上是异步的,对于和客户端原生的交互也是异步的,所以小程序的api大量采用了回调的方式,比如选择图片
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success (res) {
// tempFilePath可以作为 img 标签的 src 属性显示图片
const tempFilePaths = res.tempFilePaths
}
})
既然渲染是用webview来的,那是不是我们直接使用html标签就可以了,当然不行,不然利用a标签那不是也可以自己跳转了么?所以小程序搞了自己的一套组件系统,名为Exparser,本质还是模仿了html的那一套,但是相对的也增加了自己的一些能力,比如button,使用一些额外的参数用来获取用户信息,map可以直接使用地图的能力,ad的广告能力
小程序和app通信原理其本质和web同app通信的原理类似,只不过有渲染层和逻辑层的通信,因为双线程架构模式,安卓比较简单,不管是逻辑层还是渲染层,都是在window对象中注入一些方法,ios在渲染层采用messageHandlers特性,逻辑层则是在JavaScripCore框架注入一个全局的原生方法
整套的原理有了,根据这些原理和内容,本质上是可以能够自己实现一套小程序的体系的,但是这个工作量无疑是巨大的,既然这已经是一套成熟的方案,那如何在自己的app里面搭件一套小程序环境呢?
市面上已经存在很多开源的方案,毕竟个大厂商都已经有自己的小程序,容器技术已经成熟,比如常见的FinClip,OpenApp,mPaas,Donut等
我们以FinClip为例,毕竟FinClip能够运行微信中的小程序,并且能够保证用户体验,客户量较大,国内较为领先的小程序容器化公司,我们熟悉的像建设银行app,工商银行app等都有它的身影,有整个一套完整的小程序管理平台,端侧小程序sdk,以及自身的开发者工具,方便运营开发以及数据分析
像我们上面提到的沙箱环境,双线程的逻辑层和视图层都做成了一套通用方案
所以如果想搭件自己的一套小程序体系,使用现有的方案,安全省心,希望能给需要的同学一定的参考