🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
小程序的逻辑层与渲染层分开在不同的线程运行,这跟传统的Web 单线程模型有很大的不同,使得小程序架构上多了一些复杂度,也多了一些限制。 [TOC] ### 5.1.1 技术选型 小程序的架构设计时的要求只有一个,就是要快,包括要渲染快、加载快等。当用户点开某个小程序时,我们期望体验到的是只有很短暂的加载界面,在一个过渡动画之后可以马上看到小程序的主界面。 一般来说,渲染界面的技术有三种: 1. 用纯客户端原生技术来渲染 2. 用纯 Web 技术来渲染、 3. 用客户端原生技术与 Web 技术结合的混合技术(下称 Hybrid 技术)来渲染 小程序的宿主是微信,所以我们不太可能用纯客户端原生技术来编写小程序 。如果这么做,那小程序代码需要与微信代码一起编包,跟随微信发版本,这种方式跟开发节奏必然都是不对的。因此,我们需要像Web 技术那样,有一份随时可更新的资源包放在云端,通过下载到本地,动态执行后即可渲染出界面。 但,如果用纯 Web 技术来渲染小程序,在一些有复杂交互的页面上可能会面临一些性能问题,这是因为在 Web 技术中,UI渲染跟 JavaScript 的脚本执行都在一个单线程中执行,这就容易导致一些逻辑任务抢占UI渲染的资源。 以上,使用纯客户端原生技术或纯 Web 技术都有各自的缺点,那如果使用两者结合起来的Hybrid 技术来渲染小程序,能否优于各自独立渲染的技术方案呢?实际上,这种 Hybrid 技术在业界过去几年里演化过数种技术方案, * **PhoneGap**:早期的一个采用HTML,CSS和JavaScript的技术,创建移动跨平台移动应用程序的框架 * **React Native(下称 RN)**:近两年流行的一个 JavaScript 框架,用来编写原生的 iOS 和 Android 应用。 * **JS-SDK**: 微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。 最终,小程序选择类似于微信 JS-SDK 这样的 Hybrid 技术,即: `界面`主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力。同时,每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重。此外,界面渲染这一块我们定义了一套`内置组件`以统一体验,并且提供一些基础和通用的能力,进一步降低开发者的学习门槛。值得一提的是,内置组件有一部份较复杂组件是用客户端原生渲染的,以提供更好的性能。 ### 5.1.2 管控与安全 基于Web 技术来渲染小程序是存在一些不可控因素和安全风险的。这是因为Web技术是非常开放灵活的,我们可以利用JavaScript 脚本随意地跳转网页或者改变界面上的任意内容。 为了解决管控与安全问题,我们必须阻止开发者使用一些浏览器提供的,诸如跳转页面、操作DOM、动态执行脚本的开放性接口。要完全避免JavaScript 的灵活性以及浏览器接口的丰富性而带来的一些危险的接口,或者浏览器内核更新而新增的危险接口,小程序提供一个沙箱环境来运行开发者的JavaScript 代码。 因此,小程序的沙箱环境不能有任何浏览器相关接口,只提供纯JavaScript 的解释执行环境,那么像HTML5中的`ServiceWorker`、`WebWorker`特性就符合这样的条件,这两者都是启用另一线程来执行 JavaScript。但是考虑到小程序是一个多 WebView 的架构,每一个小程序页面都是不同的WebView 渲染后显示的,在这个架构下不好去用某个WebView中的ServiceWorker去管理所有的小程序页面。 得益于客户端系统有JavaScript 的解释引擎(在iOS下是用内置的 `JavaScriptCore框架`,在安卓则是用腾讯x5内核提供的`JsCore环境`),我们可以创建一个单独的线程去执行 JavaScript,在这个环境下执行的都是有关小程序业务逻辑的代码,也就是我们前面一直提到的逻辑层。而界面渲染相关的任务全都在WebView线程里执行,通过逻辑层代码去控制渲染哪些界面,那么这一层当然就是所谓的渲染层。这就是小程序双线程模型的由来。 ### 5.1.3 天生的延时 小程序是基于双线程模型,那就意味着任何数据传递都是线程间的通信,也就是都会有一定的延时。而传统Web技术中,当界面需要更新时,通过调用更新接口UI就会同步地渲染出来。在小程序架构里,这一切都会变成异步。 异步会使得各部分的运行时序变得复杂一些。比如在渲染首屏的时候,逻辑层与渲染层会同时开始初始化工作,但是渲染层需要有逻辑层的数据才能把界面渲染出来,如果渲染层初始化工作较快完成,就要等逻辑层的指令才能进行下一步工作。因此逻辑层与渲染层需要有一定的机制保证时序正确,这些工作在小程序框架里会处理好,开发者只需要理解生命周期,以及控制合适的时机更新UI即可。 除了逻辑层与渲染层之间的通信有延时,各层与客户端原生交互同样是有延时的。以逻辑层为例,开发者的代码是跑在逻辑层这个线程之上,而客户端原生是跑在微信主线程(安卓上是线程)之上,所以注册给逻辑层有关客户端能力的接口,实际上也是跟微信主线程之间的通信,同样意味着有延时。这也是我们看到大部分提供的接口(API)都是异步的原因。