浅析⼩程序的底层架构原理
⼀、⼩程序基础知识
⼩程序是基于WEB规范,采⽤HTML、CSS和JS等搭建的⼀套框架,官⽅给它们取的名字:WXML、WXSS,但本质上还是在整个WEB体系之下构建的。WXML说到底就是xml的⼀个⼦集。WXML采⽤⾃定义的少量标签WXSS,⼤家可以理解为就是⾃定义的CSS。实现逻辑部分的JS还是通⽤的ES规范,并且runtime还是Webview(IOS WKWEBVIEW、ANDROID X5)
1、⼩程序的组成结构
⼀个完整的⼩程序主要由以下⼏部分组成:
⼀个⼊⼝⽂件:app.js
⼀个全局样式:app.wxss
⼀个全局配置:app.json
页⾯:pages下,每个页⾯再按⽂件夹划分,每个页⾯4个⽂件
(1)视图层:wxml,wxss
see you again中文歌词(2)逻辑层:js,json(页⾯配置,不是必须)
注:pages⾥⾯还可以再根据模块划分⼦⽬录,孙⼦⽬录,只需要在app.json⾥注册时填写路径就⾏。
2、⼩程序项⽬打包:
编辑器它本⾝也是基于WEB技术体系实现的,nwjs+react,nwjs简单是说就是node+webkit,node提供给我们本地api能⼒,⽽webkit提供给我们web能⼒,两者结合就能让我们使⽤JS+HTML实现本地应⽤程序。既然有nodejs,那上⾯的打包选项⾥的功能就好实现了。
(1)ES6转ES5:引⼊babel-core的node包
(2)CSS补全:引⼊postcss和autoprefixer的node包(postcss和autoprefixer的原理看这⾥)
(3)代码压缩:引⼊uglifyjs的node包
打包后⽬录结构:
所有的⼩程序基本都最后都被打成上⾯的结构:
(1)WAService.js 框架JS库,提供逻辑层基础的API能⼒
(2)WAWebview.js 框架JS库,提供视图层基础的API能⼒
(3)WAConsole.js 框架JS库,控制台
(4)app-config.js ⼩程序完整的配置,包含我们通过app.json⾥的所有配置,综合了默认配置型
(5)app-service.js 我们⾃⼰的JS代码,全部打包到这个⽂件
(6)page-frame.html ⼩程序视图的模板⽂件,所有的页⾯都使⽤此加载渲染,且所有的WXML都拆解为JS实现打包到这⾥
(7)pages 所有的页⾯,这个不是我们之前的wxml⽂件了,主要是处理WXSS转换,使⽤js插⼊到header区域。
3、与H5页⾯的区别
赤小兔 ⼩程序和普通的 h5 页⾯到底有什么区别呢?
(1)运⾏环境:⼩程序基于浏览器内核重构的内置解析器,⽽ h5 的宿主环境是浏览器。所以⼩程序中没有 DOM 和 BOM 的相
关 API , jQuery 和⼀些 NPM 包都不能在⼩程序中使⽤;
普通⽹页开发可以使⽤各种浏览器提供的 DOM API,进⾏ DOM 操作,⽽⼩程序的逻辑层和渲染层是分开的,逻辑层运⾏在 JSCore 中,并没有⼀个完整浏览器对象,因⽽缺少相关的DOM API和BOM API。
(2)系统权限:⼩程序能获得更多的系统权限,如⽹络通信状态、数据缓存能⼒等;
(3)渲染机制:⼩程序的逻辑层和渲染层是分开的,⽽ h5 页⾯ UI 渲染跟 JavaScript 的脚本执⾏都在⼀个单线程中,互斥。所以 h5 页⾯中长时间的脚本运⾏可能会导致页⾯失去响应。
普通⽹页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运⾏可能会导致页⾯失去响应,⽽在⼩程序中,⼆者是分开的,分别运⾏在不同的线程中。
此外,⼩程序⾯对的是 iOS 和 Android 客户端和辅助开发的⼩程序开发者⼯具。根据官⽅⽂档,这三⼤运⾏环境也是有所区别的:
所以⼩程序介于 web 端和原⽣ App 之间,能够丰富调⽤功能接⼝,同时⼜跨平台。
⼆、⼩程序架构
1、双线程模型
⼩程序的框架包含两部分:View视图层、App Service逻辑层。View层⽤来渲染页⾯结构,App Service层⽤来逻辑处理、数据请求、接⼝调⽤,它们在两个进程(两个Webview)⾥运⾏。
视图层和逻辑层通过系统层的JSBridage进⾏通信,逻辑层把数据变化通知到视图层,触发视图层页⾯更新,视图层把触发的事件通知到逻辑层进⾏业务处理。
怎么更新最新版本 ⼩程序的渲染层和逻辑层分别由2个线程管理:
朴正炫(1)视图层:界⾯渲染相关的任务全都在 WebView 线程⾥执⾏。⼀个⼩程序存在多个界⾯,所以渲染层存在多个 WebView 线程。
(2)逻辑层:采⽤ JsCore 线程运⾏JS脚本。
视图层和逻辑层通过系统层的 WeixinJsBridage 进⾏通信:逻辑层把数据变化通知到视图层,触发视图层页⾯更新,视图层把触发的事件通知到逻辑层进⾏业务处理。
2、渲染流程
把开发者的 JS 逻辑代码放到单独的线程去运⾏,但在 Webview 线程⾥,开发者就没法直接操作 DOM。
那要怎么去实现动态更改界⾯呢?
如上图所⽰,逻辑层和试图层的通信会由 Native (客户端)做中转,逻辑层发送⽹络请求也经由 Native 转发。
这也就是说,我们可以把 DOM 的更新通过简单的数据通信来实现。
Virtual DOM 相信⼤家都已有了解,⼤概是这么个过程:⽤ JS 对象模拟 DOM 树 -> ⽐较两棵虚拟 DOM 树的差异 -> 把差异应⽤到真正的 DOM 树上。
页⾯渲染的具体流程是:在渲染层,宿主环境会把 WXML 转化成对应的 JS 对象,在逻辑层发⽣数据变更的时候,我们需要通过宿主环境提供的 setData ⽅法把数据从逻辑层传递到渲染层,再经过对⽐前后差异,把差异应⽤在原来的Dom树上,渲染出正确的UI界⾯。
(1)在渲染层把 WXML 转化成对应的 JS 对象。
(2)在逻辑层发⽣数据变更的时候,通过宿主环境提供的 setData ⽅法把数据从逻辑层传递到 Native,再转发到渲染层。
(3)经过对⽐前后差异,把差异应⽤在原来的 DOM 树上,更新界⾯。
杨贤硕李恩珠 我们通过把 WXML 转化为数据,通过 Native 进⾏转发,来实现逻辑层和渲染层的交互和通信。
3、双线程模型设计的好处
双线程模型是⼩程序框架与业界⼤多数前端 Web 框架不同之处。基于这个模型,可以更好地管控以及提供更安全的环境。缺点是带来了⽆处不在的异步问题(任何数据传递都是线程间的通信,也就是都会有⼀定的延时),不过⼩程序在框架层⾯已经封装好了异步带来的时序问题。
陈道明太太近照曝光 为什么要这样设计呢,前⾯也提到了管控和安全,为了解决这些问题,我们需要阻⽌开发者使⽤⼀些,例如浏览器的window对象,跳转页⾯、操作DOM、动态执⾏脚本的开放性接⼝。
我们可以使⽤客户端系统的 JavaScript 引擎(iOS 下的 JavaScriptCore 框架,安卓下腾讯 x5 内核提供的 JsCore 环境),这个沙箱环境只提供纯 JavaScript 的解释执⾏环境,没有任何浏览器相关接⼝,这就是⼩程序双线程模型的由来。
三、组件系统
我们知道⼩程序是有⾃⼰的组件的,这些基本组件就是基于 Exparser 框架。 Exparser 基于 WebComponents 的 ShadowDOM 模型,但是不依赖浏览器的原⽣⽀持,⽽且可在 纯 JS 环境中运⾏。
1、Exparser框架
Exparser是⼩程序的组件组织框架,内置在⼩程序基础库中,为⼩程序的各种组件提供基础的⽀持。⼩程序内的所有组件,包括内置组件和⾃定义组件,都由Exparser组织管理。
Exparser的主要特点包括以下⼏点:
(1)基于Shadow DOM模型:模型上与WebComponents的ShadowDOM⾼度相似,但不依赖浏览器的原⽣⽀持,也没有其他依赖库;实现时,还针对性地增加了其他API以⽀持⼩程序组件编程。
(2)可在纯JS环境中运⾏:这意味着逻辑层也具有⼀定的组件树组织能⼒。
(3)⾼效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺⼨也较⼩。
发布评论