小程序原理

微信小程序是介于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)
    用于绘制基本的窗口组件,比如组合框和窗口。
浏览器组件结构

通常而言浏览器运行在一个进程中,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微信客户端和辅助开发小程序的开发工具,这三种运行环境的区别在于:

运行环境 渲染层 逻辑层
iOS WKWebView JavaScriptCore
Android X5浏览器 X5 JSCore
小程序开发工具 Chrome WebView NWJS

小程序框架分层

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

小程序原理
  • 渲染层
    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/WXSS WebView渲染 WXML编译器把WXML文件转化为JS,构建Virtual DOM。
AppService 逻辑层,仅一个 JS JsCore运行 无法访问window/document对象

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

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

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

渲染流程

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

小程序框架

小程序框架

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

  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调用、自定义组件特性等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345