HarmonyOS 适配指南

基础库从 3.7.0 起正式支持 HarmonyOS 平台,后续与其它平台一致,通过后台灰度更新基础库,开发者工具可在详情 – 本地设置 – 调试基础库切到 3.7.0 版本进行开发调试。

架构概览

微信小程序在 HarmonyOS 平台的运行环境与安卓类似,即逻辑层的 JavaScript 代码运行在 v8 中,视图层是基于 HarmonyOS 原生的 ArkWeb 引擎来渲染,而 Skyline 渲染引擎在支持中,暂未提供。

此外,微信小程序的运行机制、更新机制、组件框架等均保持一致,但在一些特性支持度上会有区别。

适配方式

目前微信小程序在 HarmonyOS 平台与其它平台的区别主要是 HarmonyOSebView 引擎及涉及原生能力的特性上。

前者在 HarmonyOS 上使用的是 ArkWeb 引擎,可能存在一些依赖 WebView 的特性上的差异,如 CSS 样式相关,这类问题需按实际情况兼容;

后者大多是与组件/接口相关,可通过 wx.canIUse 接口或者通过 wx.getDeviceInfo().platform === 'ohos' 判断,对业务逻辑做必要的兼容。

注意:如在微信开发者工具中模拟鸿蒙,则需判断 wx.getDeviceInfo().system==’HarmonyOS’ (工具中 platform 为 devtools)

调试方式

  • 通过开发者工具调试
  1. 下载最新的nightly版开发者工具,通过最新开发者工具调试
  2. 调试基础库版本选择 3.7.0+
  3. 选择「微信小程序模式」,并选择华为鸿蒙机型
  4. 支持使用 wx.canIUse 判断接口是否可使用
  • 通过真机调试

在 HarmonyOS 的应用商店下载,安装后即可正常打开微信小程序进行调试。

支持情况

以下罗列出暂未支持的特性,对使用到未支持的特性需做好兼容。其中组件/接口具体的支持情况可跳转至对应文档查看,部分支持的一般代表少数高阶功能不支持

框架

特性 支持情况
Skyline 渲染引擎 支持中
初始渲染缓存 不支持
暗黑模式 不支持
周期性更新 不支持
数据预拉取 不支持
无障碍访问 不支持
分享朋友圈 不支持

组件

组件 支持情况
无障碍访问 不支持
keyboard-accessory 不支持
channel-live 不支持
channel-video 不支持
voip-room 不支持
map 部分支持
canvas 部分支持
ad/ad-custom 不支持
official-account 不支持
xr-frame 不支持
web-view 部分支持

接口

模块 接口 支持情况
基础-生命周期 wx.onApiCategoryChange / wx.offApiCategoryChange / wx.getApiCategory 不支持
基础-应用级事件 wx.onThemeChange / wx.offThemeChange / wx.onAudioInterruptionEnd / wx.onAudioInterruptionBegin / wx.offAudioInterruptionEnd / wx.offAudioInterruptionBegin 不支持
基础-性能 wx.preloadWebview / wx.preloadSkylineView 不支持
路由-自定义路由 支持中
跳转 wx.openEmbeddedMiniProgram / wx.onEmbeddedMiniProgramHeightChange / wx.offEmbeddedMiniProgramHeightChange 不支持
转发 wx.showShareImageMenu / wx.onCopyUrl / wx.offCopyUrl 不支持
界面-交互 wx.enableAlertBeforeUnload / wx.disableAlertBeforeUnload 支持中
界面-滚动 ScrollViewContext 不支持
界面-置顶 wx.setTopBarText 不支持
界面-窗口 不支持
界面-worklet动画 支持中
支付 wx.requestCommonPayment / wx.requestVirtualPayment / wx.openHKOfflinePayView 不支持
数据缓存-数据预拉取和周期性更新 wx.getBackgroundFetchData / wx.onBackgroundFetchData / wx.setBackgroundFetchToken / wx.getBackgroundFetchToken 不支持
数据缓存-缓存管理器 不支持
画布 部分支持
媒体-视频 wx.openVideoEditor 不支持
媒体-音频 只支持 WebAudio 不支持
媒体-音视频合成 不支持
媒体-画面录制器 不支持
媒体-视频解码器 不支持
开放接口-卡券 不支持
开放接口-发票 不支持
开放接口-生物认证 不支持
开放接口-车牌 不支持
开放接口-视频号 wx.openChannelsEvent 不支持
开放接口-微信客服 不支持
设备-联系人 wx.addPhoneContact 不支持
设备-无障碍 不支持
设备-电量 wx.onBatteryInfoChange / wx.offBatteryInfoChange 不支持
设备-网络 wx.onNetworkWeakChange / wx.offNetworkWeakChange / wx.offNetworkStatusChange 不支持
设备-屏幕 wx.onScreenRecordingStateChanged / wx.offScreenRecordingStateChanged / wx.getScreenRecordingState 不支持
设备-内存 不支持
AI 不支持
Worker 部分支持
广告 不支持
Skyline 支持中
XR-FRAME 不支持

大屏适配指南

目前市面上的用户设备大致可分为小屏的手机端、中屏的平板、大屏的 PC 端三类,而在这三类设备中又会有细小的尺寸差别,也称作屏幕碎片化。

随着微信小程序能够在越来越多的设备终端上运行,开发者也应该针对不同的屏幕尺寸进行相应的适配。

关于如何在设计、用户体验上实现更好的多端适配微信小程序,可参考微信小程序适配设计指南

1. 适配场景

按照一般的适配原则,结合微信小程序特点,通常在以下三种情况中需要进行适配:

同一类设备下,尺寸有细微差别

使用微信小程序提供的 rpx 单位,在尺寸差别不大的情况下对页面布局进行等比缩放。

在允许屏幕旋转的情况下,可分为横屏与竖屏

手机端设置 "pageOrientation": "auto" 或 iPad 上设置 "resizable": true 时会允许屏幕旋转,此时使用 Page 的 onResize 事件或者 wx.onWindowResize 方法可对该操作进行监听,进而判断是使用横屏还是竖屏布局。

不同类设备或者能够自由拖拽窗口的 PC 微信小程序

微信小程序目前是基于 Webview 实现,利用 CSS 媒体查询可实时监听屏幕尺寸大小,在不同的屏幕下展现不同的 UI 布局,结合 Flex 弹性布局、Grid 网格布局便能实现更加响应式的适配方案。

2. matchMedia – 抽象式媒体查询

微信小程序基础库基于 window.matchMedia API 新增了一组过程式与定义式接口 match-media 。开发者可以通过 <match-media>wx.createMediaQueryObserver 来显式地使用媒体查询能力,对于多端适配来说,它有以下优势:

  1. 开发者能够更方便、显式地使用 Media Query 能力,而不是耦合在 CSS 文件中,难以复用。
  2. 能够在 WXML 中结合数据绑定动态地使用,不仅能做到组件的显示或隐藏,在过程式 API 中可塑性更高,例如能够根据尺寸变化动态地添加 class 类名,改变样式。
  3. 能够嵌套式地使用 Media Query 组件,即能够满足局部组件布局样式的改变。
  4. 组件化之后,封装性更强,能够隔离样式、模版以及绑定在模版上的交互事件,还能够提供更高的可复用性。
  5. 浏览器内置 API ,能够在所有基于 Webview 的微信小程序上使用,兼容性良好。

match-media 具体使用方法可参考相关 API 文档

3. 自适应布局

为了让开发者更好的自适应大屏,微信小程序提供了 row/col 组件 供开发者使用。

自适应的主要特性是:

  • 整行最多只有 24 份,多余的排列会自动向下换行
  • 每个尺寸设置并不会影响到其它尺寸的布局

设计指引与代码示例

同时我们也提供了多端适配示例,体验路径:「扩展能力」 -> 「多端适配(需在PC端体验)」

示例微信小程序中,基于 row/col 组件 简单实现了常见的适配场景,例如:

  • 屏幕越大,布局不变,模块左右伸缩

  • 屏幕越大,内容越多,模块内容换行排列

  • 屏幕越大,布局改变,模块内容可折叠 / 展现

4. 分栏模式

在 PC 等能够以较大屏幕显示微信小程序的环境下,微信小程序支持以分栏模式展示。分栏模式可以将微信窗口分为左右两半,各展示一个页面。

frameset-screenshot

DarkMode 适配指南

微信从 iOS 客户端 7.0.12、Android 客户端 7.0.13 开始正式支持 DarkMode,微信小程序也从基础库 v2.11.0、开发者工具 1.03.2004271 开始,为开发者提供微信小程序内的 DarkMode 适配能力。

开启 DarkMode

app.json中配置darkmodetrue,即表示当前微信小程序已适配 DarkMode,所有基础组件都会根据系统主题展示不同的默认样式,navigation bar 和 tab bar 也会根据下面的配置自动切换。

相关配置

app.json中配置darkmodetrue时,微信小程序的部分配置项可以通过变量的形式来配置。在变量配置文件中定义不同主题下的颜色或图标,方法如下:

  1. app.json中配置themeLocation,指定变量配置文件 theme.json 的路径,例如:在根目录下新增theme.json,需要配置"themeLocation":"theme.json"
  2. theme.json中定义相关变量;
  3. app.json中以@开头引用变量。

支持通过变量配置的属性:

  • 全局配置的 window 属性与页面配置下的属性
    • navigationBarBackgroundColor
    • navigationBarTextStyle
    • backgroundColor
    • backgroundTextStyle
    • backgroundColorTop
    • backgroundColorBottom
  • 全局配置 window.tabBar 的属性
    • color
    • selectedColor
    • backgroundColor
    • borderStyle
    • list
      • iconPath
      • selectedIconPath

数据预拉取

预拉取能够在微信小程序冷启动的时候通过微信后台提前向第三方服务器拉取业务数据,当代码包加载完时可以更快地渲染页面,减少用户等待时间,从而提升微信小程序的打开速度 。

使用流程

1. 配置数据下载地址

数据来源为开发者服务器时支持配置灰度比例,灰度数据下载地址可以区别于数据下载地址,灰度比例不可回退,且 100% 灰度视为更新数据地址为灰度数据地址, 如需进行测试,可将灰度比例改为百分之 0,即只对开发者体验者进行灰度。

  1. 登录微信小程序 MP 管理后台,进入开发管理 -> 开发设置 -> 数据预加载,点击开启
  2. 个人主体微信小程序仅支持配置云开发环境
  3. 非个人主体微信小程序支持配置HTTPS数据下载地址、 云开发环境

2. 设置 TOKEN

用户登录微信小程序后,微信小程序可以调用 wx.setBackgroundFetchToken() 设置一个自定义 TOKEN 字符串,可以跟用户态相关,TOKEN 会在下一次预拉取或周期性更新,向开发者服务器发起请求时带上,便于服务器校验请求合法性。

Tips: wx.setBackgroundFetchToken 是可选接口,不是必须调用的。

示例:

App({
  onLaunch() {
    // 用户登录后
    wx.setBackgroundFetchToken({
      token: 'xxx'
    })
  }
})

3. 微信客户端提前拉取数据

当用户打开微信小程序时,微信服务器将向开发者服务器(上面配置的数据下载地址)发起一个 HTTP GET 请求,其中包含的 query 参数如下,数据获取到后会将整个 HTTP body 缓存到本地。

参数中 token 和 code 只会存在一个,用于标识用户身份。注意:如果选择使用 code,触发数据预拉取时可能会刷新用户登录态,详见 checkSessionKey

参数 类型 必填 说明
appid String 微信小程序标识。
token String 前面设置的 TOKEN。
code String 用户登录凭证,未设置TOKEN时由微信侧预生成,可在开发者后台调用 auth.code2Session,换取 openid 等信息。
timestamp Number 时间戳,微信客户端发起请求的时间
path String 打开微信小程序的路径。
query String 打开微信小程序的query。
scene Number 打开微信小程序的场景值。
customMiniprogramVersion String 微信小程序版本号

query 参数会使用 urlencode 处理

开发者服务器接口返回的数据类型应为字符串,且大小应不超过 256KB,否则将无法缓存数据

4. 读取数据

用户启动微信小程序时,调用 wx.getBackgroundFetchData 和 wx.onBackgroundFetchData 获取已缓存到本地的数据。

示例:

App({
  onLaunch() {
    wx.onBackgroundFetchData(() => {
      console.log(res.fetchedData) // 缓存数据
      console.log(res.timeStamp) // 客户端拿到缓存数据的时间戳
    })
    wx.getBackgroundFetchData({
      fetchType: 'pre',
      success(res) {
        console.log(res.fetchedData) // 缓存数据
        console.log(res.timeStamp) // 客户端拿到缓存数据的时间戳
        console.log(res.path) // 页面路径
        console.log(res.query) // query 参数
        console.log(res.scene) // 场景值
      }
    })
  }
})

调试方法

为了方便调试数据预拉取,工具提供了下面的调试能力给到开发者,具体可查看预拉取数据调试。

周期性更新

基础库 2.8.0 开始支持,低版本需做兼容处理。

生效条件:用户七天内使用过的微信小程序

周期性更新能够在用户未打开微信小程序的情况下,也能从服务器提前拉取数据,当用户打开微信小程序时可以更快地渲染页面,减少用户等待时间,增强在弱网条件下的可用性。

使用流程

1. 配置数据下载地址

数据来源为开发者服务器时支持配置灰度比例,灰度数据下载地址可以区别于数据下载地址,灰度比例不可回退,且 100% 灰度视为更新数据地址为灰度数据地址, 如需进行测试,可将灰度比例改为百分之 0,即只对开发者体验者进行灰度。

  1. 登录微信小程序 MP 管理后台,进入开发管理 -> 开发设置 -> 数据周期性更新,点击开启
  2. 个人主体微信小程序仅支持配置云开发环境
  3. 非个人主体微信小程序支持配置HTTPS数据下载地址、 云开发环境

2. 设置 TOKEN

用户登录微信小程序后,微信小程序可以调用 wx.setBackgroundFetchToken() 设置一个自定义 TOKEN 字符串,可以跟用户态相关,TOKEN 会在下一次预拉取或周期性更新,向开发者服务器发起请求时带上,便于服务器校验请求合法性。

Tips: wx.setBackgroundFetchToken 是可选接口,不是必须调用的。

示例:

App({
  onLaunch() {
    // 用户登录后
    wx.setBackgroundFetchToken({
      token: 'xxx'
    })
  }
})

3. 微信客户端定期拉取数据

微信客户端会在一定的网络条件下,每隔 12 小时(以上一次成功更新的时间为准)向配置的数据下载地址发起一个 HTTP GET 请求,其中包含的 query 参数如下,数据获取到后会将整个 HTTP body 缓存到本地。

参数 类型 说明
appid String 微信小程序标识
token String 前面设置的 TOKEN
timestamp Number 时间戳,微信客户端发起请求的时间

query 参数会使用 urlencode 处理

开发者服务器接口返回的数据类型应为字符串,且大小应不超过 256KB,否则将无法缓存数据

4. 读取数据

用户启动微信小程序时,调用 wx.getBackgroundFetchData() 获取已缓存到本地的数据。

示例:

App({
  onLaunch() {
    wx.getBackgroundFetchData({
      fetchType: 'periodic',
      success(res) {
        console.log(res.fetchedData) // 缓存数据
        console.log(res.timeStamp) // 客户端拿到缓存数据的时间戳
      }
    })
  }
})

调试方法

由于微信客户端每隔 12 个小时才会发起一次请求,调试周期性更新功能会显得不太方便。 因此为了方便调试周期性数据,工具提供了下面的调试能力给到开发者,具体可查看周期性数据调试。

自定义 tabBar

基础库 2.5.0 开始支持,低版本需做兼容处理。

自定义 tabBar 可以让开发者更加灵活地设置 tabBar 样式,以满足更多个性化的场景。

在自定义 tabBar 模式下

  • 为了保证低版本兼容以及区分哪些页面是 tab 页,tabBar 的相关配置项需完整声明,但这些字段不会作用于自定义 tabBar 的渲染。
  • 此时需要开发者提供一个自定义组件来渲染 tabBar,所有 tabBar 的样式都由该自定义组件渲染。推荐用 fixed 在底部的 cover-view + cover-image 组件渲染样式,以保证 tabBar 层级相对较高。
  • 与 tabBar 样式相关的接口,如 wx.setTabBarItem 等将失效。
  • 每个 tab 页下的自定义 tabBar 组件实例是不同的,可通过自定义组件下的 getTabBar 接口,获取当前页面的自定义 tabBar 组件实例。

注意:如需实现 tab 选中态,要在当前页面下,通过 getTabBar 接口获取组件实例,并调用 setData 更新选中态。可参考底部的代码示例。

使用流程

1. 配置信息

  • app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。
  • 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。

示例:

{
  "tabBar": {
    "custom": true,
    "color": "#000000",
    "selectedColor": "#000000",
    "backgroundColor": "#000000",
    "list": [{
      "pagePath": "page/component/index",
      "text": "组件"
    }, {
      "pagePath": "page/API/index",
      "text": "接口"
    }]
  },
  "usingComponents": {}
}

2. 添加 tabBar 代码文件

在代码根目录下添加入口文件:

custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss

3. 编写 tabBar 代码

用自定义组件的方式编写即可,该自定义组件完全接管 tabBar 的渲染。另外,自定义组件新增 getTabBar 接口,可获取当前页面下的自定义 tabBar 组件实例。

示例代码

在开发者工具中预览效果

skyline 模式

使用 skyline 渲染模式的时候,需要进行如下适配:

1. tabBar 组件样式兼容

  • tabBar 根组件需要添加 pointer-events: auto
  • tabBar 根组件定位需为 position: absolute
<view class="tab-bar">
  <!-- tabbar item-->
</view>
.tab-bar {
  pointer-events: auto;
  position: absolute;
}

2. getTabBar 回调函数

skyline 模式下,页面/组件上的 getTabBar 接口为异步回调的方式获取 tabBar 实例

Page({
  getInstance() {
    if (typeof this.getTabBar === 'function' ) {
      this.getTabBar((tabBar) => {
        tabBar.setData({
          selected: 0
        })
      })
    }
  }
})

skyline 示例代码

在开发者工具中预览效果

消息推送

消息推送是开放平台推出的一种主动推送服务,基于该推送服务,开发者可以及时获取开放平台的相关信息,无需调用API。 目前提供三种方式接入:

  • 开发者服务器接收消息推送
  • 云函数接收消息推送
  • 微信云托管服务接收消息推送

开发者服务器接收消息推送

总数据链路如图所示:

消息推送服务器配置

消息推送服务于微信小程序、公众号、小游戏、视频号小店、第三方平台,这里介绍微信小程序平台的配置。

填写相关信息

登录微信小程序管理后台,在「开发」-「开发管理」-「消息推送配置」中,需要填写以下信息:

  1. URL服务器地址:开发者用来接收微信消息和事件的接口 URL,必须以 http:// 或 https:// 开头,分别支持 80 端口和 443 端口。
  2. Token令牌:用于签名处理,下文会介绍相关流程。
  3. EncodingAESKey:将用作消息体加解密密钥。
  4. 消息加解密方式:
    • 明文模式:不使用消息加解密,明文发送,安全系数较低,不建议使用。
    • 兼容模式:明文和密文共存,不建议使用。
    • 安全模式:使用消息加解密,纯密文,安全系数高,强烈推荐使用。
  5. 数据格式:消息体的格式,可以选择 XML 或 JSON。

发起验证

点击“提交”后,微信服务器会对开发者服务器发起验证,请在提交前按以下方式开发: 微信服务器将发送 GET 请求到填写的服务器地址 URL 上,GET 请求携带的参数如下表所示:

参数 描述
signature 签名
timestamp 时间戳
nonce 随机数
echostr 随机字符串

其中,signature 签名的生成方式是:

  1. 将 Token、timestamp、nonce 三个参数进行字典序排序。
  2. 将三个参数字符串拼接成一个字符串,然后进行 sha1 计算签名,即可获得 signature。 开发者需要校验 signature 是否正确,以判断请求是否来自微信服务器,验签通过后,请原样返回 echostr 字符串。

举例:假设填写的 URL=”https://www.qq.com/revice”,Token=”AAAAA”。

  1. 推送的 URL 链接:https://www.qq.com/revice?signature=f464b24fc39322e44b38aa78f5edd27bd1441696&echostr=4375120948345356249&timestamp=1714036504&nonce=1514711492
  2. 将 token、timestamp、nonce 三个参数进行字典序排序,排序后结果为:[“1514711492″,”1714036504″,”AAAAA”]。
  3. 将三个参数字符串拼接成一个字符串:”15147114921714036504AAAAA”
  4. 进行 sha1 计算签名:f464b24fc39322e44b38aa78f5edd27bd1441696
  5. 与 URL 链接中的 signature 参数进行对比,相等说明请求来自微信服务器,合法。
  6. 构造回包返回微信,回包消息体内容为 URL 链接中的 echostr 参数 4375120948345356249。

为了方便开发者调试,我们提供了 URL 验证工具供开发者使用。 开发者需要填写 AccessToken、URL 地址、Token,点击“检查参数并发起验证”后,调试工具会发送 GET 请求到 URL 所指的服务器,并返回相关调试信息。

接收消息推送

当特定消息或事件触发时,微信服务器会将消息(或事件)的数据包以 POST 请求发送到开发者配置的 URL,下面以“debug_demo”事件为例,详细介绍整个过程:

消息解密方式为明文模式

  1. 假设 URL 配置为 https://www.qq.com/revice,数据格式为 JSON,Token=”AAAAA”。
  2. 推送的 URL 链接:https://www.qq.com/recive?signature=899cf89e464efb63f54ddac96b0a0a235f53aa78&timestamp=1714037059&nonce=486452656
  3. 推送的包体:
{
    "ToUserName": "gh_97417a04a28d",
    "FromUserName": "o9AgO5Kd5ggOC-bXrbNODIiE3bGY",
    "CreateTime": 1714037059,
    "MsgType": "event",
    "Event": "debug_demo",
    "debug_str": "hello world"
}
  1. 校验 signature 签名是否正确,以判断请求是否来自微信服务器。
    1. 将 token、timestamp(URL 参数中的)、nonce(URL 参数中的)三个参数进行字典序排序,排序后结果为:[“1714037059″,”486452656″,”AAAAA”]
    2. 将三个参数字符串拼接成一个字符串:”1714037059486452656AAAAA”
    3. 进行 sha1 计算签名:899cf89e464efb63f54ddac96b0a0a235f53aa78
    4. 与 URL 链接中的 signature 参数进行对比,相等说明请求来自微信服务器,合法。
  2. 回包给微信,具体回包内容取决于特定接口文档要求,如果没有特定要求,回复空串或者 success 即可。

后端 API

微信小程序还提供了一系列在后端服务器使用 HTTPS 请求调用的 API,帮助开发者在后台完成各类数据分析、管理和查询等操作。如 getAccessTokencode2Session 等。详细介绍请参考 API 文档。

access_token

access_token 是微信小程序全局唯一后台接口调用凭据,调用绝大多数后台接口时都需使用。开发者可以通过 getAccessToken 接口获取并进行妥善保存。

为了 access_token 的安全性,后端 API 不能直接在微信小程序内通过 wx.request 调用,即 api.weixin.qq.com 不能被配置为服务器域名。开发者应在后端服务器使用getAccessToken获取 access_token,并调用相关 API;

请求参数说明

  • 对于 GET 请求,请求参数应以 QueryString 的形式写在 URL 中。
  • 对于 POST 请求,部分参数需以 QueryString 的形式写在 URL 中(一般只有 access_token,如有额外参数会在文档里的 URL 中体现),其他参数如无特殊说明均以 JSON 字符串格式写在 POST 请求的 body 中。

返回参数说明

注意:当API调用成功时,部分接口不会返回 errcode 和 errmsg,只有调用失败时才会返回。

多线程 Worker

一些异步处理的任务,可以放置于 Worker 中运行,待运行结束后,再把结果返回到微信小程序主线程。Worker 运行于一个单独的全局上下文与线程中,不能直接调用主线程的方法。

Worker 与主线程之间的数据传输,双方使用 Worker.postMessage() 来发送数据,Worker.onMessage() 来接收数据,传输的数据并不是直接共享,而是被复制的。

使用流程

在开发者工具中预览效果

1. 配置 Worker 信息

app.json 中可配置 Worker 代码放置的目录,目录下的所有 JS 代码最终将被打包成一个 JS 文件:

配置示例:

{
  "workers": "workers"
}

通过以上方式配置,workers 目录下的所有 JS 文件会被打包为一个 JS 文件,并作为微信小程序首包的一部分。

微信小程序首包体积是有上限的(目前为2M),为了使 worker 代码不占用首包体积,从基础库 v2.27.3 开始支持将 worker 代码打包为一个分包。(需要更新开发者工具至最新 nightly 版本)

worker 代码配置为分包示例:

{
  "workers": {
    "path": "workers",
    "isSubpackage": true  // true 表示把 worker 打包为分包。默认 false。填 false 时等同于 { "workers": "workers" }
  }
}

2. 添加 Worker 代码文件

根据步骤 1 中的配置,在代码目录下新建以下两个入口文件:

workers/request/index.js
workers/request/utils.js
workers/response/index.js

添加后,目录结构如下:

├── app.js
├── app.json
├── project.config.json
└── workers
    ├── request
    │   ├── index.js
    │   └── utils.js
    └── response
        └── index.js

3. 编写 Worker 代码

workers/request/index.js 编写 Worker 响应代码

const utils = require('./utils')

// 在 Worker 线程执行上下文会全局暴露一个 worker 对象,直接调用 worker.onMessage/postMessage 即可
worker.onMessage(function (res) {
  console.log(res)
})

4. 在主线程中初始化 Worker

在主线程的代码 app.js 中初始化 Worker

const worker = wx.createWorker('workers/request/index.js') // 文件名指定 worker 的入口文件路径,绝对路径

从基础库 v2.27.3 开始,如果 worker 代码配置为了分包,则需要先通过 wx.preDownloadSubpackage 接口下载好 worker 代码,再初始化 Worker

var task = wx.preDownloadSubpackage({
   packageType: "workers", 
   success(res) {
      console.log("load worker success", res)
      var worker = wx.createWorker("workers/request/index.js")   // 创建 worker。 如果 worker 分包没下载完就调 createWorker 的话将报错
   },
   fail(res) {
      console.log("load worker fail", res)
   }
})

task.onProgressUpdate(res => {
  console.log(res.progress) // 可通过 onProgressUpdate 接口监听下载进度
  console.log(res.totalBytesWritten)
  console.log(res.totalBytesExpectedToWrite)
})

5. 主线程向 Worker 发送消息

worker.postMessage({
  msg: 'hello worker'
})

worker 对象的其它接口请看 worker接口说明

注意事项

  1. Worker 最大并发数量限制为 1 个,创建下一个前请用 Worker.terminate() 结束当前 Worker
  2. Worker 内代码只能 require 指定 Worker 路径内的文件,无法引用其它路径
  3. Worker 的入口文件由 wx.createWorker() 时指定,开发者可动态指定 Worker 入口文件
  4. Worker 内不支持 wx 系列的 API
  5. Workers 之间不支持发送消息
  6. Worker 目录内只支持放置 JS 文件,其他类型的静态文件需要放在 Worker 目录外
  7. 基础库 v2.18.1 开始支持在插件内使用 worker。相应地,插件使用worker前需要在plugin.json内配置workers代码路径,即一个相对插件代码包根目录的路径。

按需注入和用时注入

在微信小程序启动的过程中,除了代码包下载以外,代码注入也是一个主要的耗时环节。注入代码量的大小与内存占用与注入耗时正相关。

利用「按需注入」和「用时注入」的特性,可以优化代码注入环节的耗时和内存占用。

按需注入

基础库 2.11.1 及以上版本支持,2.11.1 以下兼容但无优化效果。 工具调试请使用 1.05.2111300 及以上版本,基础库选 2.20.1 及以上版本。

通常情况下,在微信小程序启动时,启动页面依赖的所有代码包(主包、分包、插件包、扩展库等)的所有 JS 代码会全部合并注入,包括其他未访问的页面以及未用到自定义组件,同时所有页面和自定义组件的 JS 代码会被立刻执行。这造成很多没有使用的代码在微信小程序运行环境中注入执行,影响注入耗时和内存占用。

自基础库版本 2.11.1 起,微信小程序支持通过配置,有选择地注入必要的代码,以降低微信小程序的启动时间和运行时内存。

{
  "lazyCodeLoading": "requiredComponents"
}

注意事项

  • 启用按需注入后,微信小程序仅注入当前访问页面所需的自定义组件和页面代码。未访问的页面、当前页面未声明的自定义组件不会被加载和初始化,对应代码文件将不被执行。请开发者修改配置后务必确认微信小程序的表现正常
  • 启用按需注入后,页面 JSON 配置中定义的所有组件和 app.jsonusingComponents 配置的全局自定义组件,都会被视为页面的依赖并进行注入和加载。建议开发者及时移除 JSON 中未使用自定义组件的声明,并尽量避免在全局声明使用率低的自定义组件,否则可能会影响按需注入的效果。
  • 插件包和扩展库目前暂不支持按需注入。如果需要实现插件按需加载,可以考虑将插件置于一个分包,并通过「分包异步化」的形式异步引入

用时注入

基础库 2.11.2 及以上版本支持,2.11.2 以下和未配置的效果相同。 工具调试请使用 1.05.2111300 及以上版本,基础库选 2.20.1 及以上版本。

在开启「按需注入」特性的前提下,「用时注入」可以指定一部分自定义组件不在微信小程序启动时注入,而是在真正渲染的时候才进行注入。

在已经指定 lazyCodeLoadingrequiredComponents 的情况下,为自定义组件配置 占位组件,组件就会自动被视为用时注入组件:

  1. 每个页面内,第一次渲染该组件前,该组件都不会被注入;
  2. 每个页面内,第一次渲染该组件时,该组件会被渲染为其对应的占位组件,渲染流程结束后开始注入;
  3. 注入结束后,占位组件被替换回对应组件。