ice-next icon indicating copy to clipboard operation
ice-next copied to clipboard

[RFC]统一预请求方案

Open answershuto opened this issue 1 year ago • 4 comments

现状:

PHA 中,某个 page 下面的 dataPrefetch 会编译到对应的 home-manifast 中。

export function getConfig() {
  return {
    title: 'Home',
    dataPrefetch: [
      {
        key: 'key_1',
        prefetchType: 'mtop',
        api: 'mtop.tmall.kangaroo.core.service.route.pagerecommendservice',
        v: '1.0',
        data: {
          param1: 'v1',
          param2: 'v2',
        },
        extHeaders: {
          nameAaaa: '112233',
        },
      }
    ],
  };
}

纯 Web 场景,使用 getData。

export function getData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        name: 'Home',
      });
    }, 1 * 100);
  });
}

方案

发送数据

  • 支持 PHA
    • value 为 object 的 prefetch,会被编译到 manifest 中(保持原本数据结构不变)以供在 PHA 环境中使用。
    • value 为 function 的 prefetch,会被编译成 PHA 的 worker 中调用(目前 PHA 还没支持在 worker 中注入运行时方法,需要推进支持,可以考虑先用 libmtop 发送,需要自动补全通过 event 发送到主 JS Context 并存储数据。此外,没有页面级 Worker,需要全部打到一个 Worker 中使用,这里会有个问题需要解,abc三个页面都有 function 的 prefetch,worker 在全局,是否可以保证只跑当前页面所需的 prefetch)。
  • 支持纯 Web
    • value 为 object 的 prefetch,根据类型解析称 mtop 发送。
    • value 为 function 的 preftch,直接运行匿名函数。
    • 跟现有 getData 逻辑类似,打成一个单独的 script 在主 bundle 之前执行并发送预请求。
// 多个情况
// 静态方法会包装 fetcher (默认 window.fetch)
export const dataLoader = defineDataLoader([
  {
    key: 'key_1',
    prefetchType: 'mtop',
    api: 'mtop.tmall.kangaroo.core.service.route.pagerecommendservice222',
    v: '1.0',
    data: {
      param1: 'v1',
      param2: 'v2',
    },
    extHeaders: {
      nameAaaa: '112233',
    },
  },
  async () => {
    // 当然,用户不需要同构的情况下,可以选择不用。
    const data2 = await Mtop.request({
      api: 'mtop.user.getUserSimple2',
      v: '1.0',
      data: { itemNumId: 37194529489 },
    });

    return { data, data2 };
  },
]);

// 单个静态
export const dataLoader = defineDataLoader({
  key: 'key_1',
  prefetchType: 'mtop',
  api: 'mtop.tmall.kangaroo.core.service.route.pagerecommendservice222',
  v: '1.0',
  data: {
    param1: 'v1',
    param2: 'v2',
  },
  extHeaders: {
    nameAaaa: '112233',
  },
});

// 单个动态
export const dataLoader = defineDataLoader(async () => {
  const data2 = await Mtop.request({
      api: 'mtop.user.getUserSimple2',
      v: '1.0',
      data: { itemNumId: 37194529489 },
    });

  return { data, data2 };
});

获取数据

export default function Home() {
  const data = useData('data-key'); // [null, {}, null]
}

全局的配置在 PHA 下处理不变,纯 Web 下会被构建到每一个页面下面。

PHA 改造

  • 支持 JS Worker 的 prefetch 接口,同时数据会自动同步到业务 JS Context,通过运行时 getData 获取。
  • JS Worker 需要在页面加载(非得到 manifest 以后)时可感知当前加载的是哪个页面(通过事件监听)。
  • PHA 支持 manifest 放在 HTML 中解析(SSR 场景 + 增强型 UI 能力)。
  • 动态 Prefetch(有 JS 代码的 prefetch),getData 可以生成 Fass 函数,PHA 不需要在冷启时等待 JS Engine 可运行,直发送请求到 Node 直接 prefetch,已启动 webview 的情况下,该代码可以在 JSWorker 中执行。

answershuto avatar Oct 12 '22 11:10 answershuto