前端框架:1.31.0
客户端版本:10.7.20及以上

# 简介

本功能升级可提升小程序冷启时启动页的加载速度,进而提升用户留存率。

根据平台内测数据显示:Android 设备加载速度提升30%,约为0.5秒;iOS 设备加载速度提升36%,约为0.4秒。

# 升级流程

针对已有的小程序,本次升级共有『三个改动点』,如图中绿色部分所示,可以同步进行。

升级流程

# 升级前评估

本次升级需要同时满足以下条件:

  1. 网络请求应为GET方式
  2. 网络请求需可复用,即网络请求没有参数用于校验重复请求,比如签名参数、用户登录态参数、数据加密参数等
  3. 如有动态参数,需从启动schema中提取
  4. 不能强依赖需用户实时授予的权限信息,比如地理位置数据、账户信息等

只支持单独网络请求的预拉取,不支持存在依赖关系的后续网络请求场景(比如请求B的参数依赖于请求A的返回结果,可配置请求A的预拉取能力,B请求不支持)

# 启动页选择

选择需要升级的启动页面和关键网络请求筛选,选择标准如下:

  • 启动页面:选取小程序uv/pv量级较大的页面,或运营推广的页面,比如视频播放页、内容详情页
  • 关键网络请求:没有前置依赖,并且数据返回直接影响页面有效内容开始渲染的网络请求,例如详情页的视频详情/内容详情接口

# 开发

# (1) app.json配置

在app.json中增加prefetchRules配置项,示例和说明如下:

// app.json
{
    "prefetchRules": {
        "pages/index/index": { //需要配置预拉取请求的页面,注意:每个页面配置的预拉取请求数量最多为5个
            "https://developer.***.com/${search}?a=${a}&b=2&c=3": {//请求的url模型
                "method": "GET",//请求的方法,只支持GET
                "header": { //请求的header
                    "a": "${a}",
                    "token": 1
                },
                "dataType": "json",//返回结果的类型
                "responseType": "text",//返回结果的类型
                "hitPrefetchExtraRules": { // 模糊匹配规则,只要包含以下key,并且key对应的值相等就算命中
                    "requiredQueryKeys": ["a", "b", "c"], // 不考虑顺序
                    "requiredHeaderKeys": ["a", "token"]
                }
            },
        //...
        }
    }
}

接下来会有三种情况,需要大家根据技术实现方式做对应的升级。

# (1.1) 如果关键网络请求参数数量较少,并且固定

无需额外操作

# (1.2) 如果关键网络请求存在动态参数

如果动态参数需要从启动的schema中提取,需组装预拉取网络请求数据,包含“配置变量”和“数据填充”两项内容

配置变量
  • 为了使配置的请求具有一定的动态能力,引入了“配置变量”的概念,即配置中格式为 ${XXX} 的部分,其中XXX是变量的名称,可以根据此名称对变量赋值,即将${XXX}执行字符串替换的过程,替换的字符串就是变量实际的值。
  • 配置变量的限制条件

生效范围

  • 请求URL中的 path 和 query 部分,不包含host。第一个配置变量与host之间至少有一个 “/” 或 “?” 间隔(即query、path与host之间有合法的分隔字符
  • header 参数

配置变量值的数据源:schema 中 pagePath 的 query(query中path的值实际是一个URL,将此URL解析,读取其query),示例:

    // pagePath=pages/index/index?search=searchApp 小程序打开时的协议带有这个search参数,search 的值为searchApp
    //赋值前
    {
        "prefetchRules": {
            "pages/index/index": {
                "https://developer.****.com/${search}?a=${a}&b=2&c=3": {
                    "method": "GET",
                    "header": {
                        "token": 1
                    },
                    "responseType": "",
                },
            },
        //...
        }
    }
    //赋值后
    {
        "prefetchRules": {
            "pages/index/index": {
                "https://developer.****.com/searchApp?a=1&b=2&c=3": {
                    "method": "GET",
                    "header": {
                         "token": 1
                    },
                    "responseType": "",
                },
            },
        //...
        }
    }
数据填充
  • 配置项中的 method、header、responseType、dataType 和 request API 的各项参数含义基本保持一致
  • url 中参数处理逻辑与 request 接口保持一致
  • 参数默认值:
参数名 数据类型 是否必传 默认值 说明
header object optional {'content-type': 'application/json'} 请求 header
method string optional GET 请求方法,当前仅支持GET
dataType string optional json 数据类型,默认值为json,执行json parse
responseType string optional text 响应数据类型,可选值:text

# (1.3) 如果关键网络请求参数数量较多,存在非必需参数

当请求参数数量较多时,并存在非必需参数时,预拉取请求和后续request请求参数可能不完全一致,可能存在缓存数据命中率不高的问题,需要配置缓存命中规则。

预拉取数据缓存是否命中存在两种匹配规则判断:严格精准匹配、模糊匹配,默认为严格精准匹配。

严格精准匹配

匹配每一个配置参数,只有所有参数完全一致时认为命中缓存,参数包括:

  • host
  • path
  • query
  • method
  • header
模糊匹配

由于参数可能较多,业务需求有动态变更的需求,严格精准匹配的缓存命中率可能较低,此时可以使用模糊匹配规则,要求必须存在 hitPrefetchExtraRules 配置项,不存在时退化为严格精准匹配。

// app.json
{
    "prefetchRules": {
        "pages/index/index": {
            "https://developer.****.com/${search}?a=${a}&b=2&c=3": {
              //...
                "hitPrefetchExtraRules": {
                    "requiredQueryKeys": ["a", "b", "c"],
                    "requiredHeaderKeys": ["a", "token"]
                }
            },
            //...
        },
        //...
    }
}

对照上面示例,hitPrefetchExtraRules 的规则为:

  1. 规则为一个 Map,存在两个 Key:requiredQueryKeys、requiredHeaderKeys,分别对应 query 和 header 的模糊匹配规则,如果 Key 不存在,命中的规则为相应部分的严格精准匹配
  2. requiredQueryKeys 和 requiredHeaderKeys 的值均为一个字符串数组,且不可为空,空数组和 Key 不存在处理方式一致。
  3. 在对比 query 和 header 时,如果对应的 requiredKeys 规则存在,那么只会比较 requiredKeys 数组中存在的 Key 和 Key 对应的 value 是否相等,其他值不做比较。

举例:

// 预拉取请求
"https://developer.****.com/search?a=1&b=2&c=3"

// 命中规则
{ "requiredQueryKeys": ["a", "b", "c"] }

// request 请求

// 命中
"https://developer.****.com/search?a=1&b=2&c=3&d=4"

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

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

// *******************

// 预拉取请求
"https://developer.****.com/search?a=1&b=2&c=3":{
    header:{a:1,b:2,c:3}
}

// 命中规则
{ "requiredHeaderKeys": ["a", "c"] }

// request 请求

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

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

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

# (2) request API 适配

参数变更如下:

  • 接口新增 usePrefetchCache 参数,类型为 bool,可选,默认为 false,值为 true 时表示该请求需要使用预拉取的缓存
  • 返回数据新增两个字段:
    • isPrefetch:区分数据是否为预拉取,类型为 bool ,值为 true 时表示该请求使用了预拉取的缓存
    • prefetchInfo:key-value 键值对,用于在预拉取未生效时提供对应信息。当前字段为:
      • message:中间过程的信息,类型为字符串
序号 情景 message
1 请求参数 usePrefetchCache 为 false prefetch not work because usePrefetchCache = false
2 平台管控导致 prefetch 不生效 current app network prefetch is disabled
3 当前 request 找不到匹配的可用 prefetch 配置(可能是 app.json 中 prefetchRule 有问题,或者找不到pagePath、url 等匹配的配置等情况) request url has no prefetch config
4 usePrefetchCache 为 true,有 prefetch 配置,但是因为 prefetch 请求发生错误,没有可用的prefetch 缓存 request url matching prefetch cache is invalid because of error: ERROR_MSG (可以是框架返回的error信息)
5 usePrefetchCache 为 true,有 prefetch 配置,但是因为请求没有完全匹配,没有可用的 prefetch 缓存 request url has no matching prefetch cache

示例:

//开发者配置app.json
{
    "prefetchRules":{
        "pages/index/index": {
            "https://developer1.****.com/${sid}?testid=${testid}&testdata=${testdata}":{
                "method": "GET",
                "header": {
                    "token": "xxxs1823730"
                },
                "responseType": "",
                "hitPrefetchExtraRules": {
                    "requiredQueryKeys": ["testid", "testdata"],
                    "requiredHeaderKeys": ["token"]
                }
            }
            //...
        }
        //...
    }
}
//request
ks.request({
    url: "https://developer1.****.com/${option.query.sid}?testid=${option.query.testid}&testdata=${option.query.testdata}",
    header: {"token":"xxxs1823730"},
    method: "GET",
    dataType: "json",
    responseType: "text",
    usePrefetchCache: true,
    success: (res) => {
        console.log("返回数据是否来自预拉取:", res.isPrefetch);
        console.log("预拉取提示信息:", res.prefetchInfo);
        console.log("请求数据:", res.data);
    },
});

# (3) 性能打点上报

为了更好地评估首屏数据加速的效果,框架新增了 FMP(First Meaningful Paint 是指页面的首要内容出现在屏幕上的时间)性能打点上报 API,开发者需根据业务实际情况以及 FMP 含义,在合适的位置调用。

支持版本:前端框架1.32.1(发布时间:2022.6.20);快手客户端版本:10.7.10(发布时间:2022.8.10)

代码示例:

var performance = ks.getPerformance()
performance.mark('fmp');

# FAQ

1 如果启动首页的路径为空,首屏页面数据加速会生效吗?

如果启动首页的路径为空,会进入配置的默认入口页,如果预拉取的配置中有默认入口页的配置并且满足条件,会触发该页面的预拉取行为。

2 首屏页面数据加速支持 POST 请求吗?

目前暂不支持

3 接入时遇到问题,怎么寻求支持?

建议在 开发者社区 (opens new window) 上发帖咨询,我们收到后会第一时间处理。

4 调试时 vConsole 中没有日志,应该如何处理?

有时日志输出有可能会存在一定的延迟,可以手动关闭 vConsole 后再打开尝试

5 按照文档配置后,调试时打印日志显示没有成功,应该如何排查?

可以按照如下步骤依次检查

  1. 检查是否为冷启动:首屏数据加速只会在冷启动场景生效
  2. 检查使用设备是否为商店最新版本
  3. 检查调试时启动路径和 app.json 中配置是否一致
  4. 检查$符号后的配置变量名称在启动的 schema 参数中是否存在
  5. 检查prefetchRules中的对应请求中,header的contentp-type: application/json,以及dataType: json、responseType: text 此类字段是否合理配置。
  6. 检查 hitPrefetchExtraRules 的 requiredQueryKey、requiredHeaderKeys 是否符合要求
  7. 以上步骤均已尝试后,依然没有成功,可以将打印日志截屏并提供体验包二维码寻求技术支持。

6 小程序使用了 uniapp 的技术方案开发,可以接入吗?

可以接入,但由于 uniapp 方案会在编译生成的工程中,自动构建 app.json 配置,因此需要按照如下步骤操作:

  1. 在 JS 代码中,给首屏关键网络请求对应的 request API 调用增加 usePrefetchCache=true 参数以及打印 response 的 isPrefetch、prefetchInfo 信息
  2. 使用 uniapp 编译得到可以在快手小程序开发者工具中运行的工程,手动修改 app.json 文件,增加 prefetchRules 配置
  3. 使用真机调试,通过vConsole观察打印的调试信息,遇到问题时可以按照 FAQ 第5条的方式操作
  4. 调试通过后,删除调试相关代码,重新使用uniapp编译,然后手动修改一下 app.json ,增加上面调通的 prefetchRules 配置。考虑到每次发版都需手动修改较为麻烦,自动修改的方案可以参考 uniapp发行时动态修改manifest.json参数 (opens new window) 的思路
  5. 把已经修改app.json后的工程打包提审
Copyright ©2024, All Rights Reserved