开发
API

数据预取

基础库 1.46.0 开始支持本功能

在小程序冷启动时提前发起请求,并缓存请求内容,在真实请求时读取缓存,减少网络请求的时间。具体优化时间,可以对比启动FMP耗时。

例如可以在文章详情页,商品详情页等高频访问的页面,增加数据预取的配置,可以提升页面完全展现的速度。


配置 app.json 文件

1.46.0 版本(deprecated)

会在未来的版本下线,app.json 新增prefetches配置项,用于设置预请求的所有 url 的列表,该部分 url,会在进入小程序后自动发起请求(先于开发者代码加载)。当开发者再次发起 request 请求时可以增加usePreCache参数,如果配置的 prefetch 请求已返回,则会直接返回请求结果,如果配置的 prefetch 请求还未返回,则当次 request 会继续之前未发送完成的 request 请求。

// app.json
{
    prefetches:{
        //页面路径
        "pages/index/index": [
            //请求url
           "https://developer1.bytedance.com",
           "https://developer2.bytedance.com",
           "https://developer3.bytedance.com",
           ...
        ]
        ...
    }
}

目前限定最多配置10 个页面,每个页面最多5 个预取请求,开发者服务器接口返回数据应为字符串类型,且大小不超过256K

2.18.0 版本

基本逻辑保持一致,配置方式有所改变。app.json 新增 prefetchRules 配置项,prefetchRules 优先级更高,存在此配置项时 prefetches 的配置不做处理

具体请求配置参数介绍如下:

参数名

数据类型

是否必传

默认值

说明

header

object

optional

{'content-type': 'application/json'}

请求header

method

string

optional

GET

请求方法,支持 GET ,POST

data

string/object

optional

null

请求数据,命中需完全一致(不支持GET请求传,会改为空字符串)

responseType

string

optional

text

响应数据类型,可选值:text

hitPrefetchExtraRules

object

optional

N/A

配置的 URL 模糊命中规则,如果未配置任何参数,则完全匹配

其中模糊匹配规则介绍如下:

预取规则

规则描述

requiredQueryKeys

  1. 该字段的值为一个字符串数组
  2. 该字段不存在时,命中规则为严格匹配,只有在tt.request 请求的 query 列表与预取请求的 query 列表完全相同(不考虑顺序)时才会命中
  3. 当该字段存在时,tt.request 请求需满足 requiredQueryKeys 中列出的 key 存在,且值与预取请求的值相同的情况下可命中,未列举出的参数则不影响命中

requiredHeaderKeys

  1. 该字段的值为一个字符串数组
  2. 该字段不存在时,命中规则为严格匹配,只有在tt.request 请求的 header 列表与预取请求的 header 列表完全相同(不考虑顺序)时才会命中
  3. 当该字段存在时,tt.request 请求需满足 requiredHeaderKeys 中列出的 key 存在,且值与预取请求的值相同的情况下可命中,未列举出的参数则不影响命中

新版参数配置示例

配置项中用${}包裹的称为变量,变量可以来自于打开小程序的调起协议中的 query,也可以来自于开发者 storage 中的数据,如:

// app.json
{
    "prefetchRules":{
        //页面路径
        "pages/index/index": {
            //请求url
           "https://developer1.bytedance.com?testid=${id}&testdata=${sData}":{},
           "https://developer1.bytedance.com/${sid}?testid=${id}&testdata=${sData}":{
                "method": "POST",
                "header": {
                    "testCookie": "${sCookie}",
                    "token": "xxxs1823730"
                },
                "data": {
                    "mData": "${mData}"
                },
                "responseType": "",
                "hitPrefetchExtraRules": { // 补充命中规则,只要包含以下key,且value相同就算命中
                    "requiredQueryKeys": ["id", "sData"], // 不考虑顺序
                    "requiredHeaderKeys": ["sCookie", "token"]
                }
            }
           ...
        }
        ...
    }
}

打开小程序的协议中,需要携带此参数:

pages/index/index?id=123

同时,数据预取功能会提取在小程序 storage 中存储的 key 为 sData, sCookie,mData 对应的数据,该数据需要是字符串类型。

这样,再次使用 request 发起请求时,就可以利用上 prefetchRules 中的配置。


调用 tt.request

tt.request 接口新增usePrefetchCache参数,返回数据新增isPrefetch区分数据是否为预取。以上面的配置为例:

//query
console.log(option.query.testid); //testid值为123abc
console.log(option.query.sid); //sid值为content
//storage
let testdata = tt.getStorageSync("sData"); //testdata 值为 okmijnuhb
let testCookie = tt.getStorageSync("sCookie"); //testCookie 值为 XASkasdk123123
let mData = tt.getStorageSync("mData"); //mData 值为 123123123

//request
let url =
  "https://developer1.bytedance.com/content?testid=123abc&testdata=okmijnuhb";
// 'https://developer.bytedance.com?a=中国&b=%E4%B8%AD%E5%9B%BD&c=%25E5%258C%2597%25E4%25BA%25AC'
let header = { testCookie: "XASkasdk123123", token: "xxxs1823730" };
let data = { mData: "123123123" };
let method = "POST";
let responseType = "text";
tt.request({
  url: url,
  header: header,
  data: data,
  method: method,
  dataType: "json",
  responseType: "text",
  usePrefetchCache: true,
  success: (res) => {
    console.log("返回数据是否来自预取:", res.isPrefetch);
    console.log("请求数据:", res.data);
  },
});

命中规则补充说明

由于新版的数据预取增加了很多配置,要保证数据预取的请求与真实请求完全一致,会比较困难。所以引入了 hitPrefetchExtraRules 的模糊匹配规则,模糊匹配目前只支持 query 和 header,当字段存在时,仅比较其中列出的 key,以及对应的 value 是否一致,其他的的 key 不影响命中逻辑。当 hitPrefetchExtraRules 不存在时,就会对全部参数坐严格的匹配比较。 举例说明:

// 预取请求
"https://developer.bytedance.com/search?a=1&b=2&c=3"
// 命中规则
hitPrefetchExtraRules:{ "requiredQueryKeys": ["a", "b", "c"] }

// tt.request 请求
// 命中
"https://developer.bytedance.com/search?a=1&b=2&c=3&d=4"

 // 不命中,c的值不相等
"https://developer.bytedance.com/search?a=1&b=2&c=4"

// 不命中,缺少c
"https://developer.bytedance.com/search?a=1&b=2&d=4"




// 预取请求
"https://developer.bytedance.com/search?a=1&b=2&c=3":{
  header:{a:1,b:2,c:3}
}
// 命中规则
{ "requiredHeaderKeys": ["a", "c"] }

// tt.request 请求
//不命中,query严格匹配,多了d
"https://developer.bytedance.com/search?a=1&b=2&c=3&d=4"

// 命中,b是不影响判断的key
"https://developer.bytedance.com/search?a=1&b=2&c=3":{
  header:{a:1,b:2,c:3}
}

// 不命中,a的值不一致,且缺少c
"https://developer.bytedance.com/search?a=1&b=2&c=3":{
  header:{a:3,b:2}
}

Bug & Tip

  • Tip:只会触发当次启动首页(start_page)的数据预取配置,如果 start_page 为空,会触发默认入口页的数据预取配置。配置缓存可以被用于非首页请求,缓存在当次启动生效。
  • Tip:prefetchRules 配置中的变量在 url 中只有 query 和 path 部分有效,host 部分不支持配置,且域名末尾需要保留一个/。 - developer.bytedance.com${id}形式的 url 不支持预取。
  • Tip:预请求 url 中参数处理逻辑与 tt.request 接口保持一致。
// app.json
{
    prefetchRules:{
        //页面路径
        "pages/index/index": {
            //请求url
           "https://developer.bytedance.com?a=${a}&b=${b}&c=${c}":{{
                "method": "POST",
                "header": {
                    "x": "${d}",
                    "token": 1
                },
                "data": {
                    "y": "${f}",
                    "token": 1
                },
                "responseType": "",
                "hitPrefetchExtraRules": {
                    "requiredQueryKeys": ["c"],
                    "requiredHeaderKeys": ["x", "token"]
                }
            },
           ...
        }
        ...
    }
}

信息流落地页参数处理过程如下:

// 信息流落地页配置

let a = "中国";
let b = encodeURIComponent("中国");
let c = encodeURIComponent(encodeURIComponent("中国"));
let pagePath = `pages/index/index?a=${a}&b=${b}&c=${c}`;
// pages/index/index?a=中国&b=%E4%B8%AD%E5%9B%BD&c=%25E4%25B8%25AD%25E5%259B%25BD
// pages/index/index.js

page({
  onLoad(option) {
    console.log(option.query.a); // 中国
    console.log(option.query.b); // 中国
    console.log(option.query.c); // encodeURIComponent('中国')

    let d = tt.getStorageSync("d");
    let f = tt.getStorageSync("f");
    let url =
      "https://developer.bytedance.com?a=${option.query.a}&b=${option.query.b}&c=${option.query.c}";
    // 'https://developer.bytedance.com?a=中国&b=中国&c=%E4%B8%AD%E5%9B%BD'
    let header = { x: d, token: 1 };
    let data = { y: f, token: 1 };
    let method = "POST";
    let responseType = "text";
    tt.request({
      url: url,
      header: header,
      data: data,
      method: method,
      dataType: "json",
      responseType: "text",
      usePrefetchCache: true,
      success(res) {
        console.log(`request调用成功 ${res}`);
      },
      fail(res) {
        console.log(`request调用失败`);
      },
    });

    // tt.request 会对url中参数做urlencode,已encode的参数不会重复urlencode
    // tt.request 请求开发者服务器的url
    // 'https://developer.bytedance.com?a=%E5%8C%97%E4%BA%AC&b=%E5%8C%97%E4%BA%AC&c=%E4%B8%AD%E5%9B%BD'

    // 预请求url参数处理逻辑与tt.request保持一致
    // 'https://developer.bytedance.com?a=%E5%8C%97%E4%BA%AC&b=%E5%8C%97%E4%BA%AC&c=%E4%B8%AD%E5%9B%BD'
  },
});

分享参数传递如下:

// pages/index/index.js

onShareAppMessage() {
    let a = '中国';
    let b = encodeURIComponent('中国');
    let c = encodeURIComponent(encodeURIComponent('中国'));
    let pagePath = `pages/index/index?a=${a}&b=${b}&c=${c}`;
    // pages/index/index?a=中国&b=%E4%B8%AD%E5%9B%BD&c=%25E4%25B8%25AD%25E5%259B%25BD

    return {
        title: 'title',
        desc: 'desc',
        path: pagePath,
        imageUrl: 'https://e.com/e.png',
        success() {
        },
        fail() {
        },
    };
}
// 通过分享落地页打开小程序
// pages/index/index.js

page({
  onLoad(option) {
    console.log(option.query.a); // 中国
    console.log(option.query.b); // encodeURIComponent('中国')
    console.log(option.query.c); // encodeURIComponent(encodeURIComponent('中国'))

    let url =
      "https://developer.bytedance.com?a=${option.query.a}&b=${option.query.b}&c=${option.query.c}";
    // 'https://developer.bytedance.com?a=中国&b=%E4%B8%AD%E5%9B%BD&c=%25E5%258C%2597%25E4%25BA%25AC'
    let header = { x: d, token: 1 };
    let data = { y: f, token: 1 };
    let method = "POST";
    let responseType = "text";
    tt.request({
      url: url,
      header: header,
      data: data,
      method: method,
      dataType: "json",
      responseType: "text",
      usePrefetchCache: true,
      success(res) {
        console.log(`request调用成功 ${res}`);
      },
      fail(res) {
        console.log(`request调用失败`);
      },
    });

    // tt.request 会对url中参数做urlencode,已encode的参数不会重复urlencode
    // tt.request 请求开发者服务器的url
    // 'https://developer.bytedance.com?a=%E5%8C%97%E4%BA%AC&b=%E5%8C%97%E4%BA%AC&c=%25E5%258C%2597%25E4%25BA%25AC'

    // 预请求url参数处理逻辑与tt.request保持一致
    // 'https://developer.bytedance.com?a=%E5%8C%97%E4%BA%AC&b=%E5%8C%97%E4%BA%AC&c=%25E5%258C%2597%25E4%25BA%25AC'
  },
});
点击纠错
评价此篇文档