接触小程序有一段时间了,总得来讲小程序开发门槛比较低,但其中基本的运行机制和原理仍是要懂的。“好比我在面试的时候问到一个关于小程序的问题,问小程序有window对象吗?他说有吧”,但实际上是没有的。感受他并无了解小程序底层的一些东西,归根结底来讲应该只能算会使用这个工具,但并不明白其中的道理。html
小程序与普通网页开发是有很大差异的,这就要从它的技术架构底层去剖析了。还有好比习惯Vue,react开发的开发者会吐槽小程序新建页面的繁琐,page必须由多个文件组成、组件化支持不完善、每次更改 data 里的数据都得setData、没有像Vue方便的watch监听、不能操做Dom,对于复杂性场景不太好,以前不支持npm,不支持sass,less预编译处理语言。react
“有的人说小程序就像被阉割的Vue”,哈哈固然了,他们从设计的出发点就不一样,咱也得理解小程序设计的初衷,经过它的使用场景,它为何采用这种技术架构,这种技术架构有什么好处,相信在你了解完这些以后,就会理解了。下面我会从如下几个角度去分析小程序的运行机制和它的总体技术架构。web
在小程序没有出来以前,最初微信WebView逐渐成为移动web重要入口,微信发布了一整套网页开发工具包,称之为 JS-SDK,给全部的 Web 开发者打开了一扇全新的窗户,让全部开发者均可以使用到微信的原生能力,去完成一些以前作不到或者难以作到的事情。面试
但JS-SDK 的模式并无解决使用移动网页遇到的体验不良的问题,好比受限于设备性能和网络速度,会出现白屏的可能。所以又设计了一个加强版JS-SDK,也就是“微信 Web 资源离线存储”,但在复杂的页面上依然会出现白屏的问题,缘由表如今页面切换的生硬和点击的迟滞感。这个时候须要一个 JS-SDK 所处理不了的,使用户体验更好的一个系统,小程序应运而生。npm
小程序的开发同普通的网页开发相比有很大的类似性,小程序的主要开发语言也是 JavaScript,可是两者仍是有些差异的。编程
通常来讲,渲染界面的技术有三种:小程序
经过如下几个方面分析,小程序采用哪一种技术方案微信小程序
因为小程序的宿主环境是微信,若是用纯客户端原生技术来编写小程序,那么小程序代码每次都须要与微信代码一块儿发版,这种方式确定是不行的。设计模式
因此须要像web技术那样,有一份随时可更新的资源包放在云端,经过下载到本地,动态执行后便可渲染出界面。若是用纯web技术来渲染小程序,在一些复杂的交互上可能会面临一些性能问题,这是由于在web技术中,UI渲染跟JavaScript的脚本执行都在一个单线程中执行,这就容易致使一些逻辑任务抢占UI渲染的资源。api
因此最终采用了二者结合起来的Hybrid 技术来渲染小程序,能够用一种近似web的方式来开发,而且能够实如今线更新代码,同时引入组件也有如下好处:
小程序的渲染层和逻辑层分别由 2 个线程管理:视图层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS脚本。
那么为何要这样设计呢,前面也提到了管控和安全,为了解决这些问题,咱们须要阻止开发者使用一些,例如浏览器的window对象,跳转页面、操做DOM、动态执行脚本的开放性接口。
咱们可使用客户端系统的 JavaScript 引擎,iOS 下的 JavaScriptCore 框架,安卓下腾讯 x5 内核提供的 JsCore 环境。
这个沙箱环境只提供纯 JavaScript 的解释执行环境,没有任何浏览器相关接口。
这就是小程序双线程模型的由来:
把开发者的 JS 逻辑代码放到单独的线程去运行,但在 Webview 线程里,开发者就无法直接操做 DOM。
那要怎么去实现动态更改界面呢?
如上图所示,逻辑层和试图层的通讯会由 Native (微信客户端)作中转,逻辑层发送网络请求也经由 Native 转发。
这也就是说,咱们能够把 DOM 的更新经过简单的数据通讯来实现。
Virtual DOM 相信你们都已有了解,大概是这么个过程:用 JS 对象模拟 DOM 树 -> 比较两棵虚拟 DOM 树的差别 -> 把差别应用到真正的 DOM 树上。
如图所示:
1. 在渲染层把 WXML 转化成对应的 JS 对象。
2. 在逻辑层发生数据变动的时候,经过宿主环境提供的 setData 方法把数据从逻辑层传递到 Native,再转发到渲染层。
3. 通过对比先后差别,把差别应用在原来的 DOM 树上,更新界面。
咱们经过把 WXML 转化为数据,经过 Native 进行转发,来实现逻辑层和渲染层的交互和通讯。
而这样一个完整的框架,离不开小程序的基础库。
小程序的基础库能够被注入到视图层和逻辑层运行,主要用于如下几个方面:
因为小程序的渲染层和逻辑层是两个线程管理,两个线程各自注入了基础库。
小程序的基础库不会被打包在某个小程序的代码包里边,它会被提早内置在微信客户端。
这样能够:
Exparser是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各类组件提供基础的支持。小程序内的全部组件,包括内置组件和自定义组件,都由Exparser组织管理。
Exparser的主要特色包括如下几点:
小程序中,全部节点树相关的操做都依赖于Exparser,包括WXML到页面最终节点树的构建、createSelectorQuery调用和自定义组件特性等。
内置组件
基于Exparser框架,小程序内置了一套组件,提供了视图容器类、表单类、导航类、媒体类、开放类等几十种组件。有了这么丰富的组件,再配合WXSS,能够搭建出任何效果的界面。在功能层面上,也知足绝大部分需求。
小程序启动会有两种状况,一种是「冷启动」,一种是「热启动」。假如用户已经打开过某小程序,而后在必定时间内再次打开该小程序,此时无需从新启动,只需将后台状态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的状况,此时小程序须要从新加载启动。
小程序冷启动时若是发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序须要等下一次冷启动才会应用上。 若是须要立刻应用最新版本,可使用 wx.getUpdateManager API 进行处理。
主要的优化策略能够概括为三点:
小程序的视图层目前使用 WebView 做为渲染载体,而逻辑层是由独立的 JavascriptCore 做为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具有数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上经过两边提供的 evaluateJavascript 所实现。即用户传输的数据,须要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再经过执行 JS 脚本的形式传递到两边独立环境。
而 evaluateJavascript 的执行会受不少方面的影响,数据到达视图层并非实时的。
大体从以上几个角度分析了小程序的底层架构,从小程序的由来、到双线程的出现、设计、通讯、到基础库、Exparser 框架、再到运行机制、性能优化等等,都是一个个相关而又相互影响的选择。关于小程序的底层框架设计,其实涉及到的还有不少,好比自定义组件,原生组件、性能优化等方面,都不是一点能讲完的,还要多看源码,多思考。每个框架的诞生都有其意义,咱们做为开发者能作的不仅是会使用这个工具,还应理解它的设计模式。只有这样才不会被工具左右,才能走的更远!