作者:微信支付前端工程师 王贝珊
原文链接:https://godbasin.github.io/2018/09/23/wxapp-basic-lib/
小程序的基础库,它包含了哪些东西,以及载入、更新的机制又是怎样的呢。
小程序基础库的组成
基础库成分
关于基础库的成分,不得不提到我们之前说过的小程序渲染机制,参考 React 的 Virtual DOM。
**基础库除了处理 VD 的渲染问题,它还包括内置组件和逻辑层API,总的来说负责处理数据绑定、组件系统、事件系统、通信系统等一系列框架逻辑。**
小程序的基础库是 JavaScript 编写的,它可以被注入到渲染层和逻辑层运行。在渲染层可以用各类组件组建界面的元素,在逻辑层可以用各类 API 来处理各种逻辑。
同时,小程序的一些补充能力:自定义组件和插件,也有相应的基础代码,当然也需要添加到基础库里。
所以我们可以看到,**小程序的基础库主要是**:
- **提供 VD 渲染机制相关基础代码。(Exparser 框架)**
- **提供封装后的内置组件。**
- **提供逻辑层的 API。**
- **提供其他补充能力(自定义组件和插件等)的基础代码。**
Exparser 框架
**Exparser 是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持。**小程序内的所有组件,包括内置组件和自定义组件,都由 Exparser 组织管理。
Exparser 会维护整个页面的节点树相关信息,包括节点的属性、事件绑定等,相当于一个简化版的 Shadow DOM 实现。Exparser 的主要特点包括以下几点:
- 基于 Shadow DOM 模型:模型上与 WebComponents 的 ShadowDOM 高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他 API 以支持小程序组件编程。
- 可在纯 JS 环境中运行:这意味着逻辑层也具有一定的组件树组织能力。
- 高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。
基于这个框架,内置了一套组件,以涵盖小程序的基础功能,便于开发者快速搭建出任何界面。同时也提供了自定义组件的能力,开发者可以自行扩展更多的组件,以实现代码复用。
内置组件
小程序基于 Exparser 框架,内置了一套组件,提供了视图容器类、表单类、导航类、媒体类、开放类等几十种组件。
**内置组件在小程序框架里的定义是:在小程序架构里无法实现或者实现不好某类功能,使用组件内置到小程序框架里。**常见包括:
- 开放类组件:如 open-data 组件提供展示群名称、用户信息等微信体系下的隐私信息,有 button 组件里 open-type 属性所提供分享、跳转 App 等敏感操作的能力
- 视图容器类组件:如 movable-view 这种因双线程模型导致手势识别不好实现的组件(在双线程模型中,触摸事件从渲染层发出,派发到逻辑层,这中间是有一定的延时而导致视图跟随手指运动这类交互变得有些卡顿)
API
宿主环境提供了丰富的API,可以很方便调起微信提供的能力。
小程序提供的 API 按照功能主要分为几大类:网络、媒体、文件、数据缓存、位置、设备、界面、界面节点信息还有一些特殊的开放接口。
需要注意 API 调用大多都是异步的。
自定义组件
自定义组件是开发者可以自行扩充的组件。开发者可以将常用的节点树结构提取成自定义组件,实现代码复用。
在使用自定义组件的小程序页面中,Exparser 将接管所有的自定义组件注册与实例化。以 Component 为例:
- 在小程序启动时,构造器会将开发者设置的 properties、data、methods 等定义段,写入 Exparser 的组件注册表中。
- 这个组件在被其它组件引用时,就可以根据这些注册信息来创建自定义组件的实例。
Page 构造器的大体运行流程与之相仿,只是参数形式不一样。这样每个页面就有一个与之对应的组件,称为“页面根组件”。
在初始化页面时,Exparser 会创建出页面根组件的一个实例,用到的其他组件也会响应创建组件实例(这是一个递归的过程)。
插件
插件是对一组 js 接口、自定义组件或页面的封装,用于嵌入到小程序中使用。
插件不能独立运行,必须嵌入在其他小程序中才能被用户使用;而第三方小程序在使用插件时,也无法看到插件的代码。因此,插件适合用来封装自己的功能或服务,提供给第三方小程序进行展示和使用。
插件开发者可以像开发小程序一样编写一个插件并上传代码,在插件发布之后,其他小程序方可调用。小程序平台会托管插件代码,其他小程序调用时,上传的插件代码会随小程序一起下载运行。
小程序基础库机制
基础库的载入
在开发网页时,经常会引用很多开源的 JS 库,在使用到这些库所提供的 API 前,我们需要先在业务代码前边引入这些库。
同样道理,我们需要在启动 APP 之前载入基础库,接着再载入业务代码。由于小程序的渲染层和逻辑层是两个线程管理,而我们 **一般说起基础库,也通常包括 WebView 基础库(渲染层),和 AppService 基础库(逻辑层)。**
显然,所有小程序在微信客户端打开的时候,都需要注入相同的基础库。所以,**小程序的基础库不会被打包在某个小程序的代码包里边,它会被提前内置在微信客户端。**
将基础库内置在微信客户端,有两个好处:
- 降低业务小程序的代码包大小。
- 可以单独修复基础库中的Bug,无需修改到业务小程序的代码包。
小程序的启动
**在小程序启动前,微信会提前准备好一个页面层级用于展示小程序的首页。**这里就包括了逻辑层和渲染层分别的初始化以及公共库的注入。
**在小程序启动时,微信会为小程序展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标。此时,微信会在背后完成几项工作:下载小程序代码包、加载小程序代码包、初始化小程序首页。**
基础库的更新
小程序的很多能力需要微信客户端来支撑,例如蓝牙、直播能力、微信运动等,可以说,小程序基础库的迭代离不开微信客户端的发布。
为了避免新版本的基础库给线上小程序带来未知的影响,微信客户端都是携带上一个稳定版的基础库发布的。等到微信客户端正式发布后,小程序会开始灰度推送新版本的基础库到微信客户端里,在这个过程需要仔细监控各类异常现象以及开发者和用户的反馈,一般灰度时长为12小时,灰度结束后,用户设备上就会有新版本的基础库。如果存在重大Bug,那此次推送会被回退。
参考
- 《小程序开发指南——小程序基础库的更新迭代》
- 《小程序开发指南——6.2 组件系统》
结束语
本节大致结合了小程序的启动来讲了下小程序的基础库。其实很多都能在小程序开发指南里找到,只是文字太多又有些乱,看一遍未必能记住,但是第二遍又找不到了。
哈哈哈吐槽下小程序的文档,很详细就是有点容易找不到。