数据预拉取能够在小组件冷启动时提前发起请求,并缓存请求内容,在真实请求时使用缓存数据,减少网络请求的时间。在文章详情页、商品详情页等高频访问的页面,增加数据预取配置,可以提升页面完全展现的速度。
通常来说,小组件获取网络数据是在首页 page 加载后使用 xhs.request 来实现的。在运行时,小组件开发者可以对用户可能触发的下一步流程去进行数据的提前获取。小组件数据预拉取的主要功能是在启动前,提前按照小组件配置好的规则发起网络请求并缓存,在小组件启动后直接使用缓存数据,来避免因为等待网络数据返回而展示的 loading 或页面展示不全的情况,具体流程如下:
数据预取规则需要在 app.json 中配置,示例如下:
{ "prefetchRules": { // 需要配置预取请求的页面 "pages/index/index": { // 请求的url "https://www.xiaohongshu.com/${pageid}": { // 请求的方法 "method": "POST", // 请求的header "header": { "token": "${token}" }, // POST请求的body数据 "data": { "pageSize": "${pageSize}", "pageNum": 1 }, // 返回结果的类型 "responseType": "text", // 模糊匹配规则,只要包含以下key,并且key对应的值相等就算命中 "hitPrefetchExtraRules": { // 只要请求query中以下key的value相等,则匹配成功 "requiredQueryKeys": ["a", "b", "c"], // 只要请求header中以下key的value相等,则匹配成功 "requiredHeaderKeys": ["a", "token"], // 只要请求data中以下key的value相等,则匹配成功 "requiredDataKeys": ["a.b", "c"] } } } } }
为了配置的请求可以动态化,我们引入了配置变量。配置变量的格式为 ${variable},其中 variable 是变量名。配置变量赋值的过程就是字符串替换,用变量的值替换 prefetchRules 配置字符串中的 ${variable}。 配置变量的数据源为小组件页面路由的 query 参数及开发者存储在 storage 中的数据缓存,其中页面路由的 query 参数优先级高于 storage 中的数据缓存。关于 query 和 storage 两种数据源的优缺点,如下表所示:
优点 | 缺点 | |
---|---|---|
query | 统一 | 无法针对单机,无法使用基础变量。 |
storage | 可以使用持久化的数据,可以使用运行时的数据, | 首次打开,变量不存在,无法使用。 |
构成请求最基础的就是 url,只要有完整 url 我们就可以发起请求了。目前我们支持 path,query 部分的变量替换,host 目前不支持。 当预取配置如下时,假设页面路由为pages/index/index?pageid=1000,开发者的 storage 中存储了pageSize变量,值为10,那么最终的预取请求将为 https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1
{ "prefetchRules": { "pages/index/index": { "https://www.xiaohongshu.com/${pageid}?pagesize=${pageSize}&pagenum=1": {} } } }
请求地址的值为请求参数,它包含 method,header,data 和 responseType,对应着 xhs.request API 的各项参数,这些参数也支持配置变量。method,header,data 和 responseType的默认值具体规则见下表:
参数名 | 数据类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
header | object | 否 | null | 请求 header |
method | string | 否 | GET | 请求方法,支持 GET ,POST。 |
data | string / object | 否 | null | 请求数据,命中需完全一致(GET请求不支持,会改为空字符串)。 |
dataType | string | 否 | json | data数据类型,可选值:json / application/x-www-form-urlencoded |
responseType | string | 否 | text | 响应数据类型,可选值:text、arraybuffer。 |
举个例子,假设请求参数的配置如下:
{ "https://www.xiaohongshu.com/${pageid}": { "method": "POST", "header": { "token": "${token}" }, "data": { "pageSize": "${pageSize}", "pageNum": 1 } } }
若页面路由为pages/index/index?pageid=1000,开发者的 storage 中存储了pageSize变量,值为10,同时也存储了token变量,值为test_token,那么最终的预取请求的参数将如下所示:
{ "https://www.xiaohongshu.com/1000": { "method": "POST", "header": { "token": "test_token" }, "data": { "pageSize": "10", "pageNum": 1 } } }
在判断缓存是否能复用,有精确匹配与模糊匹配两种策略。未配置 hitPrefetchExtraRules 时默认匹配规则为精确匹配,精确匹配会比较每一个配置,包括 host,path,query,method,header 等。如果请求中的冗余参数比较多,我们建议使用模糊匹配规则。下面我们来看示例配置中的最后一块,模糊匹配规则 hitPrefetchExtraRules,可以进一步提升缓存的命中率。
{ "https://www.xiaohongshu.com/${pageid}?pagesize=${pageSize}&pagenum=1": { "header": { "token": "${token}" }, "hitPrefetchExtraRules": { "requiredQueryKeys": ["pagesize", "pagenum"], "requiredHeaderKeys": ["token"], "requiredDataKeys": ["common.id", "common.info.pid"] } } }
requiredQueryKeys、requiredHeaderKeys、requiredDataKeys 规则描述: 该字段的值为一个字符串数组; 该字段不存在时,命中规则为严格匹配,只有在 xhs.request 请求的配置和预取请求的配置,完全相同时才会命中; 当该字段存在时,在对比配置的 query 、 header、data 时,只会比较在 requiredKeys 数组中的 key 和 key 对应的 value 是否相等,其他值不做比较。
示例如下:
// 预取请求 "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1" // 命中规则 { "hitPrefetchExtraRules" :{"requiredQueryKeys": ["pagesize", "pagenum"]} } // xhs.request 请求 // 命中 "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1&other=1&other2=2" // 不命中,pagenum值不相等 "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=2&other=1&other2=2" // 不命中,缺少pagesize "https://www.xiaohongshu.com/1000?pagenum=1&other=1&other2=2"
// 预取请求 "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1":{ header:{ token: "test_token", other: 1 } } // 命中规则 { "requiredHeaderKeys": ["token"] } // xhs.request 请求 // 不命中,query 严格匹配,多了 other "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1&other=1" // 命中,other 为不影响判断的 key "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1":{ header:{ token: "test_token", other: 5 } } // 不命中,token的值不一致 "https://www.xiaohongshu.com/1000?pagesize=10&pagenum=1":{ header:{ token: "test", other: 1 } }
xhs.request新增了usePrefetchCache 参数,返回数据新增 isPrefetch 区分数据是否为预取,示例如下:
// app.json中配置的预取规则 { "prefetchRules": { "pages/index/index": { "https://www.xiaohongshu.com?testid=${id}&testdata=${sData}": {}, "https://www.xiaohongshu.com/${sid}?testid=${id}&testdata=${sData}": { "method": "POST", "header": { "testCookie": "${sCookie}", "token": "xxxs1823730" }, "data": { "mData": "${mData}" }, "responseType": "", "hitPrefetchExtraRules": { "requiredQueryKeys": ["testid", "testdata"], "requiredHeaderKeys": ["testCookie", "token"] } } } } }
//storage const testCookie = xhs.getStorageSync("sData"); const sCookie = xhs.getStorageSync("sCookie"); const mData = xhs.getStorageSync("mData"); //request const token = "xxxs1823730"; const { sid, testid } = option.query; const url = `https://www.xiaohongshu.com/${sid}?testid=${testid}&testdata=${sData}`; const header = { testCookie, token }; const data = { mData }; xhs.request({ url, header, data, method: "POST", dataType: "json", responseType: "text", // 如果需要使用预取结果缓存,必须添加 usePrefetchCache: true usePrefetchCache: true, success: (res) => { console.log("返回数据是否来自预取:", res.isPrefetch); console.log("请求数据:", res.data); }, });
xhs.request 接口新增 usePrefetchCache 参数,返回数据新增 isPrefetch 来验证是否为预取返回的数据,以表明预加载配置无误及生效。
xhs.request({ url: https://developer.xiaohongshu.com/develop?sku=abc&price=123 method: 'GET', //添加usePrefetchCache配置 usePrefetchCache: true, header: { 'content-type': 'application/json', }, dataType: 'json', responseType: 'text', success(data) { console.log('====> isPrefetch', data.isPrefetch) } })
一、首页情况
二、非首页的二跳场景