目录

小程序原理

小程序原理

微信小程序是介于Native和WebApp之间的产物,它依托浏览器WebView展示同时可以调用原生能力,比如获取通讯录、拍照等,同一份代码可运行在Android、iOS和微信调试开发工具内。

与React Native的跨平台不同的是,小程序大部分UI组件并不是原生渲染,还是类似WebApp使用浏览器渲染。 Native 组件层在 WebView 层之上,只有少量组件使用 Native 实现,比如 <canvas><video><map><textarea>

浏览器运行环境

浏览器主要组件包括

  • 用户界面(User Interface)

    地址栏、前进后退按钮、书签菜单等

  • 浏览器引擎(Browser Engine)

    在用户界面和呈现引擎之间传递指令

  • 呈现引擎(Renderering Engine)

    负责显示请求的内容

  • JavaScript解释器

    用于解释和执行JavaScript代码

  • 网络(Networking)

    用于网络调用,比如HTTP请求,其接口与平台无关并为所有平台提供实现。

  • 数据存储(Data Persistence)

    数据持久层,浏览器在本地磁盘上保存的数据。比如Cookie、网络数据库等。

  • 用户界面后端(UI Backend)

    用于绘制基本的窗口组件,比如组合框和窗口。

https://i-blog.csdnimg.cn/blog_migrate/921367332f3ef791b75e47e0fc2bd127.png

浏览器组件结构

通常而言浏览器运行在一个进程中,Google Chrome比较特殊每个标签都是一个独立的进程。浏览器是多线程的,重要的线程包括

  • 呈现引擎(渲染引擎):运行在UI线程中
  • JS解释器(JS解释引擎):运行在JS引擎线程中

浏览器中UI渲染线程和JS引擎线程是互斥的,当JS引擎线程执行时UI渲染引擎线程会被挂起,UI更新时会被保存在一个队列中等到JS引擎线程空闲时会立即被执行。

小程序与网页开发

  • 网页开发

    网页开发渲染线程和脚本线程是互斥的,网页开发使用浏览器暴露的DOM API进行DOM选中操作,网页开发者面对的环境是各种浏览器。

  • 小程序

    小程序的渲染层和逻辑层是分开运行在不同的线程中,逻辑层运行在JSCore中因此没有一个完整的浏览器对象,因而缺少DOM API和BOM API。JSCore和NodeJS环境不同,NPM包在小程序中无法运行。小程序开发需面对iOS和Android两大操作系统。

小程序与H5页面区别

  • 运行环境

    小程序是基于浏览器内核重构的内置解析器,H5的宿主环境是浏览器。所以小程序中没有DOM和BOM相关的API,jQuery和NPM包无法在小程序中使用。

  • 系统权限

    小程序能够获得更多的系统权限,比如网络通信状态、数据缓存能力等。

  • 渲染机制

    小程序的逻辑层和渲染层是分开的,H5页面UI渲染跟JS脚本执行都在一个单线程中而互斥,因此H5页面中长时间的脚本执行会导致页面失去响应。

小程序和Web页面对比

  • 静态UI界面差别不大
  • Web页面交互存在卡顿不如原生顺畅
  • Web页面切换生硬不如原生流畅
  • Web页面加载存在白屏不如原生体验好

导致这些问题的主要原因是因为Web页面是基于DOM,在生成和操作DOM耗时且耗性能,另外浏览器对于网页渲染都是单线程处理的方式,包括布局、渲染、JS执行(阻塞)、图像解码等。浏览器重绘时页面刷新频率为60FPS,即16ms/frame,如果16毫秒内不能完成DOM操作就会出现跳帧。Web页面没有GPU图形加速页导致UI界面不流畅。因此,现在的Vue、React等前端框架都推崇使用虚拟DOM,以间接地减少DOM操作频率。

小程序运行环境

小程序开发面对的是iOS和Android微信客户端和辅助开发小程序的开发工具,这三种运行环境的区别在于:

运行环境渲染层逻辑层
iOSWKWebViewJavaScriptCore
AndroidX5浏览器X5 JSCore
小程序开发工具Chrome WebViewNWJS

小程序框架分层

小程序的框架包括两部分分别是View渲染层和AppService逻辑层

https://i-blog.csdnimg.cn/blog_migrate/c301605cfb776fa89907f87ab6afbab2.png

小程序原理

  • 渲染层

    View层用来渲染页面结构,渲染层界面使用WebView进行渲染,一个小程序存在多个界面所以渲染层存在多个WebView线程。

  • 逻辑层

    逻辑层采用JSCore线程运行JS脚本,进行逻辑处理、数据请求、接口调用等。

    逻辑层会将数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。

视图层和逻辑层分别在两个WebView进程中运行,视图层和逻辑层通过系统层的JSBridge进行通信,逻辑层将数据变化通知到视图层,触发视图层页面更新,视图层将触发的事件通知到逻辑层进行业务处理。

小程序的这两个线程的通信经由客户端进行中转,逻辑层把数据变化通知到渲染层,触发渲染层面更新,渲染层把触发的事件通知到逻辑层进行业务处理。

小程序的UI视图和逻辑处理使用多个WebView实现,逻辑处理的JS代码会全部加载到一个WebView中称之为AppService,整个小程序只有一个且整个生命周期常驻内存,所有的视图(WXML和WXSS)都是单独的WebView来承载即AppView。所以一个小程序打开时至少存在2个WebView进程,正是因为每个视图都是一个而独立的WebView进程,考虑到性能消耗,小程序不允许打开超过5层级的页面,同时也是为了更好的体验。

对于AppService可理解为一个页面主要功能是负责逻辑处理部分的执行,底层提供了一个WAService.js文件来提供API接口,接口主要是消息通信封装的WeixinJSBridge。

小程序线程模型

双线程模型

小程序的渲染层和逻辑层分别由两个线程进行管理,小程序运行时有两个线程分别是View视图线程和AppService逻辑线程,这两个线程是相互隔离的,通过桥接协议WeixinJsBridge进行通信。

  • 逻辑层

    界面渲染相关任务在WebView线程中执行,一个小程序可以存在多个界面,所以渲染层存在多个WebView线程。

  • 逻辑层

    逻辑层采用JsCore线程运行JS脚本

线程模块代码原理备注
View视图层,可多个WXML/WXSSWebView渲染WXML编译器把WXML文件转化为JS,构建Virtual DOM。
AppService逻辑层,仅一个JSJsCore运行无法访问window/document对象

小程序的视图层线程和逻辑层线程是如何进行数据传递的呢?

通过两边提供的 evaluateJavascript 实现,即用户传输的数据需将其转换为字符形式传递,同时把转换后的数据内容拼接成为一份JS脚本,再通过执行JS脚本的形式传递到两边独立的环境中。也就是说,两个线程是通过系统层的WeixinJsBridge来通信的,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层今昔那个业务处理。

页面渲染的具体流程是在渲染层宿主环境会将WXML转化为对应的JS对象,在逻辑层发生数据变更时需通过宿主环境提供的 setData 方法将数据从逻辑层传递到渲染层,对比前后差异后将差异应用到原来的DOM树上,以渲染出正确的UI界面。

https://i-blog.csdnimg.cn/blog_migrate/331f769bac8e78c54da689ef9bd42d58.png

渲染流程

小程序双线程模型与Web前端框架不同之处在于,小程序双线程模型可以更好地管控和提供更加安全的环境,缺点是带来无处不在的异步问题,因为任何数据传输都是线程间通信,也就存在一定的延迟,不过小程序在框架层面已经封装了异步带来的时序问题。

小程序框架

https://i-blog.csdnimg.cn/blog_migrate/c97c1dbf7e4786f8d9c6aa40924eb86d.png

小程序框架

从下往上看,小程序的解析顺序

  1. 最底层是微信,当开发版式小程序开发工具会把代码和框架一起进行打包,微信中打开小程序时微信会将打包好的代码下载到微信App中,这样就可以像在开发工具里一样在微信中运行小程序。
  2. native层是小程序的框架,框架封装了UI层组件和逻辑层组件,这些组件可以通过微信App提供的接口调用手机硬件信息。
  3. 最上层是需进行操作的视图层和逻辑层,视图层和逻辑层的交互式通过数据经由native层进行交互的,视图层和逻辑层可调用native框架中封装好的组件和方法。

小程序生命周期

小程序生命周期可分为应用生命周期和页面生命周期两部分

  • 应用生命周期
  1. 用户首次打开小程序会触发 onLaunch 事件,全局只触发一次。
  2. 小程序初始化完成后会触发 onShow 事件,监听小程序显示。
  3. 小程序从前台进入后台会触发 onHide 事件
  4. 小程序从后台进入前台显示会触发 onShow 事件
  5. 小程序后台运行一定时间或系统资源占用过高时会被销毁
  • 页面生命周期
  1. 小程序注册完成后会加载页面并触发 onLoad 事件方法
  2. 页面载入后会触发 onShow 事件方法而显示页面
  3. 首次显示页面会触发 onReady 方法,渲染页面元素和样式,一个页面只会调用一次。
  4. 当小程序后台运行或跳转到其它页面时会触发 onHide 事件方法
  5. 当小程序由后台进入到前台运行或重新进入页面时会触发 onShow 方法
  6. 当使用重定向 wx.redirectTo() 方法或关闭当前页面返回上一页 wx.navigateBack() 方法时会触发 onUnload 事件方法。

小程序组件系统

小程序的基本组件是基于Exparser框架的,Exparser基于WebComponents的ShadowDOM模型,不依赖浏览器的原生支持,可在纯JS环境中运行。小程序所有节点树操作都依赖于Exparser,包括WXML到页面最终节点树的构建, CreateSelectorQuery 调用、自定义组件特性等。