# 小程序使用总结

如题,小程序现在很普及,公司的前端不是在写 H5 页面,就是在写小程序,这篇文章并不是写小程序代码的编写,而是总结小程序原理部分。

  • 小程序的特点
  • 小程序的架构
  • 小程序运行机制
  • 小程序开发经验

# 小程序特点

小程序之所以发展迅猛,主要是基于以下五个特点:

  • 跨平台:小程序跨越 android 和 ios 平台,降低开发成本降低了门槛。
  • 流量大:共享微信平台 9 亿多的用户的流量,可以更方便地进行推广。
  • 成本低:类 web 端开发模式,开发者可以更快地上手。
  • 轻应用:无需下载注册,用完即走。
  • 高体验:可以媲美原生 app 操作体验。

小程序为什么快?

  • native 预先额外加载一个 webView,当打开指定页面时,用默认数据直接渲染,请求数据回来时局部更新。
  • 返回上一个页面时,直接显示历史 view。
  • 退出小程序,view 状态不销毁。

# 小程序架构

微信小程序的框架包含两部分 view 视图层、appService 逻辑层,view 层用来渲染页面结构,appService 层用来逻辑处理、数据请求、接口调用,它们在两个线程里运行。

视图层使用 webView 渲染,逻辑层使用 jsCore 运行。

视图层包括 wxml 文件和 wxss 文件。逻辑层包括我们写的 js。视图层和逻辑层采用 jsBridge 进行通信。逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。

小程序架构图

# 视图层

视图层由 wxml 与 wxss 编写,由组件来进行展示。视图层的主要工作:将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。

# WXML

WXML(WeiXin Markup Language),类比 web 开发中的 html。支持特性如下:

  • 支持数据绑定。
  • 支持逻辑算术运算。
  • 支持模板引用。
  • 支持添加事件(bindtap)。

wxml 运行流程: WXML运行流程

# WXSS

WXSS(WeiXin Style Sheets),类比 web 开发中的 css。支持特性如下:

  • 支持大部分 css 特性。
  • 添加尺寸单位 rpx,可根据屏幕宽度自适应。
  • 不支持多层选择器-避免被组件内结构破坏。(因为生成到 webView 中的 dom 树和实际的 wxml 会有差异。)

wxss 运行流程: WXSS运行流程

# 小程序组件

小程序提供了一系列组件用于开发业务功能,类比 html 中的语义化标签。

小程序组件

小程序的组件基于 webComponent 标准,使用 polymer 框架进行实现。

# 源生组件

目前 native 实现的组件有 <canvas/> <video/> <map/> <textarea/>

native 组件层在 webView 层之上。

# 逻辑层

逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

逻辑层主要功能:

  • App 小程序的入口。
  • Page 页面的入口。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 每个页面有独立的作用域,并提供模块化能力。
  • 数据绑定、事件分发、生命周期管理、路由管理。

逻辑层

如图所示:

  • 一个小程序包含 1 个逻辑层和多个视图层。
  • 每打开一个页面,就会创建一个新的 webView,创建 webView 是比较消耗资源和耗时的,所以微信限制最多只能嵌套 10 层。

逻辑层的运行环境在不同客户端下并不相同。

  • ios - jsCore。
  • android - x5 js 解析器。
  • devTool - nwjs chrome 内核。

# 小程序运行机制

小程序启动会有两种情况,一种是冷启动,一种是热启动。

  • 热启动。如果用户已经打开过某小程序,在一定时间内再次打开该小程序,此时无需重新启动,只需将后台状态的小程序切换到前台。
  • 冷启动。用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。

# 运行机制

  • 小程序没有重启的概念。
  • 当小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间后(目前是 5 分钟)会被微信主动销毁。
  • 当短时间内(5s)连续收到两次以上收到系统内存告警,会进行小程序的销毁。

小程序运行图

# 更新机制

小程序冷启动时如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。如果需要马上应用最新版本,可以使用 wx.getUpdateManager API 进行处理。

# 小程序开发经验

  • 小程序可以借鉴的优点
  • 小程序存在的问题

# 小程序可以借鉴的优点

  • 提前新建 webView,准备新页面渲染。
  • view 层和逻辑层分离,通过数据驱动,不直接操作 dom。
  • 使用 virtual dom,进行局部更新。
  • 全部使用 https,确保传输中安全。
  • 使用离线能力。
  • 前端组件化开发。
  • 使用 rpx 单位,隔离设备尺寸,方便开发。

# 小程序存在的问题

  • 小程序仍然使用 webView 渲染,并非原生渲染。
  • 需要独立开发,不能在非微信环境运行。
  • 开发者不可以扩展新组件。
  • 服务端接口返回的头无法执行,比如:set-cookie。
  • 依赖浏览器环境的 js 库不能使用,因为是 jsCore 执行的,没有 window、document 对象。
  • wxss 中无法使用本地(图片、字体等)。
  • wxss 转化成 js 而不是 css,为了兼容 rpx。
  • wxss 不支持级联选择器。
  • 小程序无法打开页面,无法拉起 app。
  • 小程序不能和公众号重名,于是小程序的名字就成了:自选股+、滴滴出行 DiDi。

# 常见的开发优化

# setData 优化

当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 js 脚本,再通过执行 js 脚本的形式传递到两边独立环境。

应避免以下操作,可能会造成页面卡顿。

  • 频繁的去 setData。
  • 每次 setData 都传递大量新数据。
  • 后台态页面进行 setData。

# 代码包大小的优化

开发者在实现业务逻辑同时也有必要尽量减少代码包的大小,因为代码包大小直接影响到下载速度,从而影响用户的首次打开体验。除了代码自身的重构优化外,还可以从这两方面着手优化代码大小:

  • 分包加载,对小程序进行分包,可以优化小程序首次启动的下载时间
  • 清理没有使用到的代码和资源

目前小程序打包是会将工程下所有文件都打入代码包内,也就是说,这些没有被实际使用到的库文件和资源也会被打入到代码包里,从而影响到整体代码包的大小。

# 预加载优化

小程序在启动时,会直接加载所有页面逻辑代码进内存,即便 page2 可能都不会被使用。在 page1 跳转至 page2 时,page1 的逻辑代码 js 数据也不会从内存中消失。page2 甚至可以直接访问 page1 中的数据。

小程序的这种机制差异正好可以更好的实现预加载。通常情况下,我们习惯将数据拉取写在 onLoad 事件中。但是小程序的 page1 跳转到 page2,到 page2 的 onLoad 是存在一个 300ms ~ 400ms 的延时的。

因为小程序的特性,完全可以在 page1 中预先拿取数据,然后在 page2 中直接使用数据,这样就可以避开 redirecting 的 300ms ~ 400ms 了。最简单的使用,是在路由跳转时,先请求数据,然后将数据挂载到全局对象中,在新页面直接读取。

# 相关链接

微信小程序架构解析