如何深入分析小程序运行原理?

共 4445字,需浏览 9分钟

 ·

2021-04-10 10:18

深入分析小程序运行原理

背景

小程序凭借其高曝光率、开发成本低、运行更流畅等优势和特点,一经推出就被广泛使用,面对小程序的火爆,自然而然地,就有很多开发者转战小程序领域,本文主要带大家了解下小程序运行环境背后的故事,

但对于想要学习了解这些内部架构来说,目前市面上的教程更多是告诉你如何使用现有规则开发一款小程序功能,少有说明白一套小程序内部机制是如何运行起来的。本文我会详细分享小程序的运行原理。

为了更方便友好地理解本文的一些内容,我们先对小程序的运行环境进行一个大概的分析,然后从下面三个层面来加深对小程序运行原理的理解

  • 开发者工具分析破解
  • 核心文件解读和
  • 架构流程图解

小程序运行环境

根据微信小程序开发文档可以得知小程序在三端的运行环境场景:

  • iOS :小程序逻辑层的 JavaScript 代码运行在 JavaScriptCore() 中,视图层是由 WKWebView 来渲染的
  • Android:小程序逻辑层的JavaScript 代码运行在 V8 中,视图层是由自研 XWeb 引擎基于 Mobile( )Chrome() 内核来渲染的
  • 开发工具:小程序逻辑层的JavaScript 代码是运行在 NW.js 中,视图层是由 Chromium() Webview 来渲染的

从小程序在三端中的运行环境可以看出来,它们存在逻辑层和渲染层之间的交互,具体是如何交互的呢?我们可以从渲染层和逻辑层之间的通信模型来找答案:

从这张图中,我们可以看出小程序采用了一种较为合适的技术方案,实现渲染层和逻辑层分别由2个线程管理:

  • 渲染层的界面使用了WebView进行渲染
  • 逻辑层采用JsCore线程运行JS脚本

当一个小程序存在多个界面时,渲染层就会存在多个WebView线程,这两个线程之间的通信会经由微信客户端来做中转,逻辑层发送的网络请求也经由Native转发,

为什么要采用这种技术方案呢?

主要原因是小程序的管控限制,比如不能直接操作DOM树、页面跳转等管控措施,更好地形成自己的生态闭环。

现在我们已经对小程序运行环境的基本组成有了一些了解,下面我就从开发者工具分析破解、文件解读和架构流程图解这三个层面来讲述小程序运行环境的具体知识点。

开发者工具分析破解

我们先从微信开发者工具分析破解说起,首先,我们从微信开发者工具中打开官方提供的小程序demo项目:

从编辑栏和文档中,我们可以知道一个页面的组成结构存在四种文件格式

  • .js后缀文件表示当前页面逻辑
  • .wxml 后缀文件是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构
  • .wxss 后缀文件用于表示一套样式语言,用于描述 WXML 的组件样式
  • .json 后缀文件表示是页面的配置原则

这些是我们大部分开发者看到或知道的一些表面内容。你可能会问,什么是深层次的内容呢?下面我们就来一一分析。

刚才我们也讲到了小程序中存在逻辑层和渲染层,那怎么在开发者工具中发现它呢?

鼠标操作 微信开发者工具–》调试–》调试微信开发者工具

之后就会弹出这样一个页面:

可以看到我做了两处标记,第一处标记的webview是渲染层,每个页面src对应一个地址,第二处标记的webview就是逻辑层。

仅仅是这样一个页面,我们是没办法直接查看webview中的具体内容的,还需要一些操作。你可以在刚才打开的控制台Console中输入找到对应标签,查看对应的webview:


再通过这个命令查看具体的webview内容:


如果你直接打开对应的dom树,第一个webview展示的就是渲染层相关信息:

比如从这张图中我们就可以看到这个页面渲染层所依赖的一些文件和一些方法,通过结果论来推断这些文件从何而来有何作用。

而对于service逻辑层的webview,可以直接在开发者工具右下方控制台Console输入document,这样就能查看了:

经过上面的介绍,你就能知道,通过dom树和source资源可以看出加载的一些本地文件资源。那么接下来,我再告诉你如何找到这些文件的出处,包含文件本身的引用和代码执行返回的结果。

我们从刚才那张图中看到script引入了一些WA开头的文件,这些文件其实就是小程序运行时核心的基础库文件了,我们在控制台输入openVendor()命令,会自动弹出对应的文件框:

这些.wxvpkg后缀文件就是微信基础库的版本文件,通过相关工具解压后可以看到文件内容格式:

需要特别注意的是,还存在两个wccwcsc可执行文件,这两个文件有什么作用呢?

wcc 将微信小程序设计的一套wxml标签语言,用于构建出页面结构,转为WebView可以理解的标签,毕竟渲染层还是运行在webview中,我们可以通过一张图来看下它的编译流程。

它的编译流程大致过程是

  • 先加载小程序所有页面中wxml格式的文件代码
  • 将它们转换成一个$gwx(pagePath)的js函数,注入到webview中
  • 在小程序运行时,可以知道当前的页面路径,执行这个函数会生成该页面的结构函数,之后接受页面数据,输出一段描述页面结构的virtual() dom json对象
  • 最后通过小程序内部组件生成页面对应的HTML标签,页面标签通过wcc编译转化成我们熟悉的节点。

那么wxss文件的作用是什么呢?它主要负责把wxss内容转换为视图可使用的css内容,它同时会分析文件之间的引用关系,添加尺寸单位rpx转换,还能根据屏幕宽度自适应以及样式导入,最后会生成一个eval()()函数用于处理rpx,输出一个样式信息数组。

小程序核心基础库文件解读

刚才我们看到了小程序运行时核心的基础库文件,其中WAservice.js、WAwebView.js、appservice.js等文件是承载小程序运行环境的最核心文件,所以,有必要对这几个文件进行重点解读,

先来看下WAservice.js文件,直接打开它是一个打包混淆后的文件,有大约6万多行:

为了更直观、更具可读性,我们可以使用js-beautify美化,在VS Code采用函数缩放,可以使代码的可读性大大增高。图片: https://uploader.shimo.im/f/sDqXRZ5fvmLFmTVI.png

这样一看其实很清晰了,我们可以看到一些常听说的微信对象,比如:

  • WeixinJSBridge:用于消息通信封装调用,主要微信环境与native,开发环境与开发者工具后台服务的通信
  • appServiceEngine:()用于定义页面全局的方法,如define,require, App,Page,Component,getApp等
  • virtualDOM:和Vue、React中virtualDOM实现相似,但这里它主要模拟了DOM 接口上面的element() 对象
  • expraser:它是用于框架组件的方法定义,意味着逻辑层也具有一定的组件树组织能力。

还有一些其他对象和内容就不描述了,感兴趣的话,你可以自己下载下来看看。

经过上面的美化和工具处理,可以看到对象里面有很多个function(e,t,n)文件,对应的就是每个暴露的方法,下面要做的就是把这些方法的代码手动反编译回正常可读性高的源码文件。

小程序架构图及运行流程

通过对小程序运行环境和核心文件的了解,你可能对小程序的运行原理有了一个比较零散的认识,知道了小程序运行原理的一些特征和要素,下面我们通过小程序整体的架构层级图和运行流程来系统地了解它的运行原理。

从这张图中,自上而下可以看出大致的一个层次结构:

  • 展现层:这是小程序的页面显示,包括菜单、标题等展示内容
  • 控制层:包括 UI 控制、中枢控制
  • 消息处理层:包含了通信消息分发处理、缓存
  • 服务层就是包括网络、存储、文件等服务还可以看到,基础设施层包括日志文件、数据存储
  • 基础本地层是访问本身设备相机通讯等功能
  • 操作系统层就是运行载体平台,比如 ios、Android

了解了小程序的架构图,接下来我们从运行环境流程层面来分析启动时controller webview 和通讯之间的关系。

  • 首会先加载小程序系统配置文件:主要包含app.json相关文件和场景。
  • 然后创建 service webview自动连接到socket server获取网络信息,
  • 再根据配置创建 page webview用于解析主页路径创建主页 Webview。
  • 之后通知 Socket Server 路由信息,在pagewebview 创建之前,发送 onAppRoute 信息,
  • 创建后,发onAppRouteDone信息通知,并且Socket server转发控制层信息到 appservice,
  • 最后APPSERVICE 通知PAGEFRAME 渲染, PAGEFRAME 告知APPSERVICE 渲染的状态。

可能你听完这些内容会有点不知所云,前面没有提到有消息通知说明啊,但其实在微信开发者工具,有一个消息中心底层模块维持着一个WebSocket服务器,

小程序逻辑层的WebView和渲染层的WebView通过WebSocket与开发者工具底层建立长连,使用WebSocket的protocol字段来区分Socket的来源,

那么,具体来说,消息处理的类型发送和接收是怎么做的呢?

主要是通过不同的消息类型来进行处理,常见的几种消息类型如下:

  1. APPSERVICE_ON_EVENT 消息由控制层发出,APPSERVICE和WEBVIEW层接收后无需处理直接callback

  2. APPSERVICE_INVOKE 消息由APPSERVICE层发出,APPSERVICE和WEBVIEW层接收后处理对应的api方法实现,再按需callback

  3. APPSERVICE_PUBLISH 消息由APPSERVICE发出,WEBVIEW层接收后无需处理直接callback

  4. WEBVIEW_ON_INVOKE 消息由WEBVIEW层发出,WEBVIEW层接收后处理对应的api方法实现,再按需callback

  5. WEBVIEW_PUBLISH 消息由WEBVIEW发出,APPSERVICE层接收后无需处理直接callback

以上就是小程序工具端实现的一些消息类型和传输方式,当然在客户端肯定不会直接采用socket方式进行链接,因为在客户端上处理效率性能和稳定性问题不是最合适宜的解决方案、

总结

本文主要是从开发者工具破解、小程序核心基础库文件解读和小程序架构这三个层面来讲述小程序的环境运行原理。需要注意的重点内容是,我们要知道小程序与普通网页区别采用了渲染层和逻辑层,还要知道自定义的标签和样式怎么编译转换成webview可以识别节点和样式,另外,消息通信与处理也需要重点学习。

浏览 57
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报