独立分包

微信客户端 6.7.2,基础库 2.3.0 及以上版本开始支持。开发者工具请使用 1.02.1808300 及以上版本,可 点此下载。

独立分包是微信小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。从独立分包中页面进入微信小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。

开发者可以按需将某些具有一定功能独立性的页面配置到独立分包中。当微信小程序从普通的分包页面启动时,需要首先下载主包;而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度。

一个微信小程序中可以有多个独立分包。

小游戏在基础库 v2.12.2 开始支持独立分包,详见 小游戏独立分包指南

配置方法

假设微信小程序目录结构如下:

├── app.js
├── app.json
├── app.wxss
├── moduleA
│   └── pages
│       ├── rabbit
│       └── squirrel
├── moduleB
│   └── pages
│       ├── pear
│       └── pineapple
├── pages
│   ├── index
│   └── logs
└── utils

开发者通过在app.jsonsubpackages字段中对应的分包配置项中定义independent字段声明对应分包为独立分包。

{
  "pages": [
    "pages/index",
    "pages/logs"
  ],
  "subpackages": [
    {
      "root": "moduleA",
      "pages": [
        "pages/rabbit",
        "pages/squirrel"
      ]
    }, {
      "root": "moduleB",
      "pages": [
        "pages/pear",
        "pages/pineapple"
      ],
      "independent": true
    }
  ]
}

限制

独立分包属于分包的一种。普通分包的所有限制都对独立分包有效。独立分包中插件、自定义组件的处理方式同普通分包。

此外,使用独立分包时要注意:

  • 独立分包中不能依赖主包和其他分包中的内容,包括 js 文件、template、wxss、自定义组件、插件等(使用 分包异步化 时 js 文件、自定义组件、插件不受此条限制)
  • 主包中的 app.wxss 对独立分包无效,应避免在独立分包页面中使用 app.wxss 中的样式;
  • App 只能在主包内定义,独立分包中不能定义 App,会造成无法预期的行为;
  • 独立分包中暂时不支持使用插件。

注意事项

(1)关于 getApp()

与普通分包不同,独立分包运行时,App 并不一定被注册,因此 getApp() 也不一定可以获得 App 对象:

  • 当用户从独立分包页面启动微信小程序时,主包不存在,App也不存在,此时调用 getApp() 获取到的是 undefined。 当用户进入普通分包或主包内页面时,主包才会被下载,App 才会被注册。
  • 当用户是从普通分包或主包内页面跳转到独立分包页面时,主包已经存在,此时调用 getApp() 可以获取到真正的 App

由于这一限制,开发者无法通过 App 对象实现独立分包和微信小程序其他部分的全局变量共享。

为了在独立分包中满足这一需求,基础库 2.2.4 版本开始 getApp 支持 [allowDefault] 参数,在 App 未定义时返回一个默认实现。当主包加载,App 被注册时,默认实现中定义的属性会被覆盖合并到真正的 App 中。

示例代码:

  • 独立分包中
const app = getApp({allowDefault: true}) // {}
app.data = 456
app.global = {}
  • app.js 中
App({
  data: 123,
  other: 'hello'
})

console.log(getApp()) // {global: {}, data: 456, other: 'hello'}

(2)关于 App 生命周期

当从独立分包启动微信小程序时,主包中 ApponLaunch 和首次 onShow 会在从独立分包页面首次进入主包或其他普通分包页面时调用。

由于独立分包中无法定义 App,微信小程序生命周期的监听可以使用 wx.onAppShow,wx.onAppHide 完成。App 上的其他事件可以使用 wx.onError,wx.onPageNotFound 监听。

低版本兼容

在低于 6.7.2 版本的微信中运行时,独立分包视为普通分包处理,不具备独立运行的特性。

注意:在兼容模式下,主包中的 app.wxss 可能会对独立分包中的页面产生影响,因此应避免在独立分包页面中使用 app.wxss 中的样式。

分包预下载

基础库 2.3.0 开始支持,低版本需做兼容处理。 开发者工具请使用 1.02.1808300 及以上版本,可点此下载。

开发者可以通过配置,在进入微信小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。

分包预下载目前只支持通过配置方式使用,暂不支持通过调用API完成。

vConsole 里有preloadSubpackages开头的日志信息,可以用来验证预下载的情况。

配置方法

预下载分包行为在进入某个页面时触发,通过在 app.json 增加 preloadRule 配置来控制。

{
  "pages": ["pages/index"],
  "subpackages": [
    {
      "root": "important",
      "pages": ["index"],
    },
    {
      "root": "sub1",
      "pages": ["index"],
    },
    {
      "name": "hello",
      "root": "path/to",
      "pages": ["index"]
    },
    {
      "root": "sub3",
      "pages": ["index"]
    },
    {
      "root": "indep",
      "pages": ["index"],
      "independent": true
    }
  ],
  "preloadRule": {
    "pages/index": {
      "network": "all",
      "packages": ["important"]
    },
    "sub1/index": {
      "packages": ["hello", "sub3"]
    },
    "sub3/index": {
      "packages": ["path/to"]
    },
    "indep/index": {
      "packages": ["__APP__"]
    }
  }
}

preloadRule 中,key 是页面路径,value 是进入此页面的预下载配置,每个配置有以下几项:

字段 类型 必填 默认值 说明
packages StringArray 进入页面后预下载分包的 rootname__APP__ 表示主包。
network String wifi 在指定网络下预下载,可选值为:
all: 不限网络
wifi: 仅wifi下预下载

限制

同一个分包中的页面享有共同的预下载大小限额 2M,限额会在工具中打包时校验。

如,页面 A 和 B 都在同一个分包中,A 中预下载总大小 0.5M 的分包,B中最多只能预下载总大小 1.5M 的分包。

分包异步化

微信小程序中,不同的分包对应不同的下载单元;因此,除了非独立分包可以依赖主包外,分包之间不能互相使用自定义组件或进行 require。「分包异步化」特性将允许通过一些配置和新的接口,使部分跨分包的内容可以等待下载后异步使用,从而一定程度上解决这个限制。

在开发者工具中预览效果

兼容性

该特性需要基础库版本 2.11.2 或以上,使用该特性的微信小程序在 2.11.2 以下的基础库上可能无法工作,如果发布正式版本,可以考虑将最低基础库版本设置为 2.11.2 或以上。

点击展开各平台最低支持版本:
  • 安卓微信:7.0.13
  • iOS 微信:7.0.12
  • 微信开发者工具:1.05.2104272
  • PC 微信:3.4.5
  • macOS 微信:3.4.1
  • 安卓企业微信:3.1.23
  • iOS 企业微信:4.0.8

跨分包自定义组件引用

一个分包使用其他分包的自定义组件时,由于其他分包还未下载或注入,其他分包的组件处于不可用的状态。通过为其他分包的自定义组件设置 占位组件,我们可以先渲染占位组件作为替代,在分包下载完成后再进行替换。例如:

// subPackageA/pages/index.json
{
  "usingComponents": {
    "button": "../../commonPackage/components/button",
    "list": "../../subPackageB/components/full-list",
    "simple-list": "../components/simple-list",
    "plugin-comp": "plugin://pluginInSubPackageB/comp"
  },
  "componentPlaceholder": {
    "button": "view",
    "list": "simple-list",
    "plugin-comp": "view"
  }
}

在这个配置中,buttonlist 两个自定义组件是跨分包引用组件,其中 button 在渲染时会使用内置组件 view 作为替代,list 会使用当前分包内的自定义组件 simple-list 作为替代进行渲染;在这两个分包下载完成后,占位组件就会被替换为对应的跨分包组件。

在基础库 2.24.3 之后,可以使用 wx.onLazyLoadError 监听加载事件。

跨分包 JS 代码引用

一个分包中的代码引用其它分包的代码时,为了不让下载阻塞代码运行,我们需要异步获取引用的结果。如:

// subPackageA/index.js
// 使用回调函数风格的调用
require('../subPackageB/utils.js', utils => {
  console.log(utils.whoami) // Wechat MiniProgram
}, ({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
require.async('../commonPackage/index.js').then(pkg => {
  pkg.getPackageName() // 'common'
}).catch(({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})

在其它分包中的插件也可以通过类似的方法调用:

// 使用回调函数风格的调用
requirePlugin('live-player-plugin', livePlayer => {
  console.log(livePlayer.getPluginVersion())
}, ({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
requirePlugin.async('live-player-plugin').then(livePlayer => {
  console.log(livePlayer.getPluginVersion())
}).catch(({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})

详情可参考 require 文档

按需注入和用时注入

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

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

按需注入

基础库 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. 注入结束后,占位组件被替换回对应组件。

多线程 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代码路径,即一个相对插件代码包根目录的路径。

后端 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,只有调用失败时才会返回。

消息推送

消息推送是开放平台推出的一种主动推送服务,基于该推送服务,开发者可以及时获取开放平台的相关信息,无需调用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 即可。

自定义 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 示例代码

在开发者工具中预览效果

周期性更新

基础库 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 个小时才会发起一次请求,调试周期性更新功能会显得不太方便。 因此为了方便调试周期性数据,工具提供了下面的调试能力给到开发者,具体可查看周期性数据调试。

数据预拉取

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

使用流程

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) // 场景值
      }
    })
  }
})

调试方法

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