AICon上海|与字节、阿里、腾讯等企业共同探索Agent 时代的落地应用 了解详情
写点什么

从源码看微信小程序启动过程

  • 2020-03-11
  • 本文字数:3672 字

    阅读完需:约 12 分钟

从源码看微信小程序启动过程

一、写作背景

接触小程序一年多,真实体验就是小程序开发门槛相对而言确实比较低。不过小程序的开发方式,一直是开发者吐槽的,如习惯了 Vue,React 开发的开发者经常会吐槽小程序一个 Page 必须由多个文件组成,组件化支持不完善或者说不能非常愉快的开发组件。在以前小项目中没太大感觉,从加入有赞,参与有赞微商城小程序的开发,是真切的体会到对于大型小程序项目开发的复杂性。


有赞从微信小程序内测就开始开发小程序,在不支持自定义组件的时代,只能通过 import 的形式拆分模块或实现组件。在业务复杂的页面,可能会 import 非常多的模块,而相应的 wxss 也需要 import 样式,除了操作繁琐,有时候也难免遗漏。


作为开发者,我们当然希望可以让工作更简单,更愉快,也希望改善我们的开发方式。所以希望能够更了解微信小程序框架,减少不必要的试错,于是有了一次对小程序框架的 debug 之旅。(基础库 1.9.93)


通过三周空余时间的 debug,也算对小程序框架有了一些浅显的认识,达到了最初的目的;对小程序启动,实例,运行等有了真切的体会。这篇文章记录了小程序框架的基本代码结构,启动流程,以及程序实例化过程。


本文的目的是希望把我看到的分享给对小程序感兴趣或者正在开发小程序的读者,主要解答“框架对传入的对象等到底做了什么”。

二、从启动流程一窥小程序框架细节

在开发者工具中使用 help() 方法,可以查看一些指令和方法。使用其中的 openVendor 方法可以打开微信开发者工具在小程序框架所在目录。其中以包括以基础库命名的目录和其他帮助文件,如其中有两个工具 wcc,wcsc。wcc 可把 wxml 转换为对应的 JS 函数 —— $gwx(path, global),wcsc 可将 wxss 转换为 css。而基础库目录包括 WAService.js 和 WAWebview.js 文件。小程序框架在开发者工具中以 WAService.js 命名(WAWebview.js 不知其作用,听说在真机环境使用该文件)。


在开发中工具命令行使用 document.head 可以查看到小程序的启动流程大致如下:



以小节的方式分别介绍这些流程,小程序是如何处理的(小节编号与图中编号相同)。

1、初始化全局变量

下图是小程序启动是初始化的一些全局的变量:



那些使用“__”开头,未在文档中提及可使用变量是不建议使用的,__wxAppCode__ 在开发者工具中分为两类值,json 类型和 wxml 类型。以 .json 结尾的,其 key 值为开发者代码中对应的 json 文件的内容,.wxml 结尾的,其 key 值为通过调用 $gwx(’./pages/example/index.wxml’) 将得到一个可执行函数,通过调用这个函数可得到一个标识节点关系的 JSON 树。


2、加载框架(WAService.js)

使用工具对 WAService.js 进行格式化后进行 debug。可以发现小程序框架大致由: WeixinJSBridgeNativeBufferwxConsoleWeixinWorkerJavaScript兼容(这部分为猜测)、 Reporterwxexparser__virtualDOM____appServiceEngine__ 几部分组成。


其中除了 wxWeixinJSBridge 这两个基础 API 集合, exparser, __virtualDOM__, __appServiceEngine__ 这三部分作为框架的核心, __appServiceEngine__ 提供了框架最基本的接口如 App,Page,Component; exparser 提供了框架底层的能力,如实例化组件,数据变化监听,view 层与逻辑层的交互等;而 __virtualDOM__ 则起着链接 __appServiceEngine__exparser 的作用,如对开发者传入 Page 方法的对象进行格式化再传入 exparser 的对应方法处理。


框架对外暴露了以下 API:Behavior,App,Page,Component,getApp,getCurrentPages,definePlugin,requirePlugin,wx。

3、业务代码的加载

在小程序中,开发者的 JavaScript 代码会被打包为


define('xxx.js', function(require, module, exports, window, document, frames, self, location, navigator, localStorage, history, Caches, screen, alert, confirm, prompt, fetch, XMLHttpRequest, WebSocket, webkit, WeixinJSCore, Reporter, print, WeixinJSBridge) {  'use strict';
// your code})
复制代码


这里的 define 是在框架中定义的方法,在框架中提供了两个方法:require 和 define 用来定义和使用业务代码。其方式有些像 AMD 规范接口,通过 define 定义一个模块,使用 require 来应用一个模块。但是也有很大区别,首先 define 限制了模块可使用的其他模块,如 window,document;其次 require 在使用模块时只会传入 require 和 module,也就是说参数中的其他模块在定义的模块中都是 undefined,这也是不能在开发者工具中获取一些浏览器环境对象的原因。


在小程序中,JavaScript 代码的加载方式和在浏览器中也有些不同,其加载顺序是首先加载项目中其他 js 文件(非注册程序和注册页面的 js 文件),其次是注册程序的 app.js,然后是自定义组件 js 文件,最后才是注册页面的 js 代码。而且小程序对于在 app.js 以及注册页面的 js 代码都会加载完成后立即使用 require 方法执行模块中的程序。其他的代码则需要在程序中使用 require 方法才会被执行。


下面详细介绍了 app.js,自定义组件,页面 js 代码的处理流程。

4、加载 app.js 与注册程序

在 app.js 加载完成后,小程序会使用 require(‘app.js’) 注册程序,即对 App 方法进行调用,App 方法是对 __appServiceEngine__.App 方法的引用。


下图是框架对于 App 方法调用时的处理流程:



App 方法根据传入的对象实例化一个 app 实例,其生命周期函数 onLaunch 和 onShow 因为使用不同的方式获取 options 的参数。在有些需要根据场景值来实现需求的,或许使用 onShow 中的场景值更合适。


在实际开发过程中发现,在微信顶部唤起小程序和在小程序列表唤起的 options 也是不一样的。在该案例中通过点击分享的小程序进入后,关闭小程序,再通过不同方式进入小程序,通过顶部唤起的还是 options 的 path 属性还是分享出来的 path,但是通过列表中打开直接回到了首页,这里 App 中的 onShow 就会获取到不同的 options。

5、加载自定义组件代码以及注册自定义组件

自定义组件在 app.js 之后被加载,小程序会在这个过程中加载完所有的自定义组件(分包中自定义组件没有有测试过),并且是加载完成后自动注册,只有注册完成后才会加载下一个自定义组件的代码。


下图是框架对于 Component 方法处理流程:



图中介绍了框架如何对传入 Component 方法的对象的处理,其后面还有很多深入的对于组件实例化的步骤没有在图中表示出来,具体可以在文章最后的附件中查看。


自定义组件在小程序中越来越完善,其拥有的能力也比 Page 更强大,而后面会提到在使用自定义组件的 Page 中,Page 实例也会使用和自定义组件一样的实例化方式,也就是说,他拥有和自定义组件一样的能力。

6、加载页面代码和注册页面

加载页面代码的处理流程和加载自定义组件一样,都是加载完成后先注册页面,然后才会加载下一个页面。


下图是注册一个页面时框架对于 Page 方法的处理流程:



Page 方法会根据是否使用自定义组件做不同的处理。使用自定义组件的 page 对象会被处理为和自定义组件的结构,并在页面实例化时使用不同的处理流程进行实例化。当然对于开发而言没任何不同。


从图中可以发现 Page 传入的(生命周期)代码并不会在这里被执行,可以通过下面小节了解 Page 实例化的详细过程。

7、等待页面 Ready 和 Page 实例化

还记得上面介绍的启动流程中最后一步等待页面 Ready?严格来讲是等待浏览器 Ready,小程序虽然有部分原生的组件,不过本质上还是一个 web 程序。


在小程序中切换页面或打开页面时会触发 onAppRoute 事件,小程序框架通过 wx.onAppRoute 注册页面切换的处理程序,在所有程序就绪后,以 entryPagePath 作为入口使用 appLaunch 的方式进入页面。


下图是处理导航的程序流程:



从图中可以看出页面的实例化是在进入页面时进行,下图是具体的实例化过程:



下图是最终可得到 Page 实例:



可以发现其中多了 onRouteEnd API,实际该接口不会被调用。其中以 component 标记的表示只有在使用了自定义组件时才会有的方法和属性。在前面第 5 小节提到了对于使用自定义组件的页面会按照自定义组件方式解析,这些属性和方法与自定义组件表现一致。

8、关于 setData

小程序框架是一个以数据驱动的框架,当然不能少了对他如何实现数据绑定的探索,下图是 Page 实例的 setData 执行流程:



其中 component:setData 表示使用自定义组件的 Page 实例的 setData 方法。

三、写在最后

这是一次不完全的小程序框架探索,是在微信开发工具中 debug 的结果。虽然对于实际开发没有什么太大的帮助,但是对框架如何对开发的 js 代码进行处理有了一个很明确的认识,在使用一些 js 特性时可以有明确的感知。如果你还疑惑“小程序框架对传入的对象等到底做了什么”那一定是我表达能力太差,说声对不起。


通过这一次 debug ,也给我引入了新的问题,还希望能够有更多的讨论:


  • 自定义组件太多启动时会耗时处理自定义组件

  • 文件太多会耗时读文件

  • 合理的设计分包很重要


一份在调试过程中的笔记 小程序框架不完全分析.xmind,如果看官有兴趣可以下载看看。当然最后对于框架中已有的能力,还是非常希望微信可以开放更多稳定的接口,并在文档中告知开发者,让开发变得简单一些。


2020-03-11 22:191045

评论

发布
暂无评论
发现更多内容

为什么很多互联网公司很少做单元测试?

博文视点Broadview

AWS 亚马逊云科技 1 亿美金入局AIGC,哪些AI云服务已经可以对标微软、谷歌?

B Impact

基于smardaten无代码快速开发一个智慧城管系统

陈橘又青

无代码开发

对线面试官-Redis(作为缓存的一致性问题)

派大星

Java 面试题

干掉Navicat?阿里Chat2DB来了!

王磊

Java 数据库

在 BI 工具 Tableau 中使用 databend

Databend

《生死狙击》研发商无端科技使用RDS倚天ARM架构数据库,实现增效降本

阿里云瑶池数据库

RDS 阿里云瑶池数据库

从幕后走到台前!过去十年,我们在阿里云如何建设可观测体系?

阿里巴巴云原生

阿里云 云原生 可观测

费报只是小 case!电子影像系统,工作效率up无限

风来兮

管理 技术管理 电子档案 财务 数字化工具

怎样确保舞台LED显示屏的安全

Dylan

安全性 环境 维护 LED显示屏 户内led显示屏

精选8道ES高频面试题和答案,后悔没早点看。

王中阳Go

elasticsearch 面试题 go面试题 后端面试题 ES面试题

Hive执行计划之只有map阶段SQL性能分析和解读

不在线第一只蜗牛

sql 开发语言 开发框架

利用Flutter和小程序容器打造更强大的用户体验

FinFish

flutter 小程序 跨端开发 小程序容器 跨端框架

Go 语言中 database/sql 是如何设计的

江湖十年

数据库 后端 Go 语言 数据库操作

千万级规模微服务稳定性技术揭秘:隔离策略

HelloGeek

微服务 高并发 稳定性 隔离性

行业分析| 无人机电力巡检的应用

anyRTC开发者

人工智能 音视频 无人机 快对讲 视频监控

C语言中.与->的用法介绍

芯动大师

语音厅源码实用功能屏幕的转换

山东布谷科技

软件开发 源码搭建 语音源码 语音厅平台搭建

表单设计领域天花板,表单引擎最全设计

codebee

OpenCV开箱即用的功能

互联网工科生

OpenCV C++

Java又双叒叕“凉”了?

程序员小毕

Java spring 面试 springboot SpringCloud

建筑产业变革肇始,华为提笔写下新《营造法式》

脑极体

全屋智能

官宣!2023云原生编程挑战赛正式启动

阿里巴巴云原生

阿里云 云原生 云原生编程挑战赛

Java并行流指北

javalover123

并行 Java' 并行流

OSPFv3:第三版OSPF除了支持IPv6,还有这些强大的特性!

wljslmz

OSPF 6 月 优质更文活动

如何扩展及优化CI/CD流水线?

SEAL安全

CI/CD 优化 扩展

历史首次!阿里云与浙大斩获数据库顶会SIGMOD最佳论文,成果已在PolarDB中落地

阿里云瑶池数据库

阿里云 polarDB 瑶池数据库 SIGMOD

量子程序设计基础 | 量子程序与量子编程

TiAmo

量子计算 量子编程 6 月 优质更文活动

C语言实现单链表-增删改查

DS小龙哥

6 月 优质更文活动

从源码看微信小程序启动过程_文化 & 方法_有赞技术_InfoQ精选文章