小程序底层架构剖析( 二 )


小程序底层架构剖析

文章插图

小程序底层架构剖析

文章插图
 
WXSS动态适配WXSS是小程序中使用的样式语言,WXSS具有css的大部分特性,同时它对CSS进行了扩充以及修改 。
小程序中使用的尺寸单位为rpx(Responsive px),不同于h5中对于px的处理,需要使用postcss进行统一的转换,小程序底层已经为开发者做好了这层转换,那具体它是怎么做到的呢?
小程序底层架构剖析

文章插图
我们看它的这段源码,其实它与阿里的flexible.js方案是类似的,不同的是它做了一个精度收拢的优化,主要是为了解决1px的问题 。
WXSS同样会经过编译,最终的编译产物为wxss.js,不同于WXML通过script标签的形式插入到渲染层,wxss.js则是通过eval的方式注入到渲染层代码中 。
渲染层webview全局变量: 渲染线程中存在着以下全局变量 。
  • webviewId:webview的唯一标识,当用户打开一个小程序页面的时候,相当于打开了一个webview,不同的webview用webviewid来区分;
  • wxAppCode:整个页面的json wxss wxml编译之后都存储在这里;
  • Vd_version_info:版本信息;
  • ./dev/wxconfig.js:小程序默认总配置项,包括用户自定义与系统默认的整合结果 。在控制台输入__wxConfig可以看出打印结果;
  • ./dev/devtoolsconfig.js:小程序开发者配置,包括navigationBarHeight,标题栏的高度,状态栏高度,等等,控制台输入__devtoolsConfig可以看到其对应的信息;
  • ./dev/deviceinfo.js:设备信息,包含尺寸/像素点pixelRatio;
  • ./dev/jsdebug.js:debug工具;
  • ./dev/WAWebview.js:渲染层底层基础库;
  • ./dev/hls.js:优秀的视频流处理工具;
  • ./dev/WARemoteDebug.js:底层基础库调试工具;
那小程序是如何快速启动一个webview的呢?
我们在打开pages/index/index视图页面时,发现DOM中多加载了一个__pageframe__/pageframe.html的视图层 。这个视图层的作用正是小程序提前为一个新的页面层准备的 。小程序每个视图层页面内容都是通过pageframe.html模板来生成的,包括小程序启动的首页 。
下面来看看小程序为快速打开小程序页面做的技术优化:
  • 首页启动时,即第一次通过pageframe.html生成内容后,后台服务会缓存pageframe.html模板首次生成的html内容;
  • 非首次新打开页面时,页面请求的pageframe.html内容直接走后台缓存;
  • 非首次新打开页面时,pageframe.html页面引入的外链js资源走本地缓存; 这样在后续新打开页面时,都会走缓存的pageframe的内容,避免重复生成,快速打开一个新页面 。
视图层打开新页面的流程
在创建每个视图层页面的webview时,都会为其绑定了onLoadCommit事件(它会在页面加载完成后触发,包含当前文档的导航和副框架的文档加载) 。初始时webview的src会被指定为空页面地址http://127.0.0.1:${global.proxyPort}/aboutblank?${c},其中c为对应webview的id 。webview从空页面到具体页面视图的过程如下:
  1. 空页面地址webview加载完毕后执行事件中的reload方法,即设置webview的src为pageframe地址;
  2. 加载完成后,设置其src为pageframe.html, 新的src内容加载完成后再次触发onLoadCommit事件但根据条件不会执行reload方法;
  3. pageframe.html页面在dom ready之后触发注入并执行具体页面相关的代码,此时通过history.pushState方法修改webview的src但是webview并不会发送页面请求;
设计思路-逻辑层接下来我们看看小程序在逻辑层都做了哪些事情 。
逻辑层与视图层通信
在小程序中,逻辑层只有一个,但是渲染层有多个,渲染层和逻辑层之间是通过微信客户端进行桥接通信的 。那具体是怎么实现的呢?其实它使用的就是WeixinJSBridge通信机制 。
在小程序执行的过程中,微信客户端分别向渲染层和逻辑层注入WeixinJSBridge,WeixinJSBridge主要提供了以下几个方法: