@datatester/op
v0.2.3
Published
## 介绍
Downloads
25
Keywords
Readme
火山引擎 A/B 测试开放 SDK
介绍
火山引擎 A/B 测试开放 SDK 方便用户集成 A/B 页面,提升集成体验。提供微前端/iframe 都集成方式,省掉用户大部分的手动配置。
安装
npm install @datatester/op
Api
微前端(MFE)加载方式
opInit(for React & Vue)
使用微前端加载器时需要提前执行 opInit,opInit 的作用是初始化微前端相关的资源。
| 字段 | 子类型 | 类型 | 说明 | 是否必填 | 默认值 | | ------------------ | --------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ------------------------------ | | remote | | string | 微前端资源链接 | 是 | - | | base | | string | string[] | 主项目的路由前缀,用于进行主项目和微前端应用间进行路由映射,看见恶意以字符串的形式传入单个 base,也可以以数组的形式传入多个 base | 是 | - | | source | | string | 依赖的 AB 网站源地址,主要用于私有化环境的配置 | 否 | https://console.volcengine.com | | styleEncapsulation | | enum | 样式隔离策略 | 否 | styleGC | | | styleGC | | 记录载入应用所插入的样式(包括 css-in-js 样式),并在卸载时移除,载入时确保样式在插入节点的后面位置以确保高优先级 | | | | | scopedCSS | | 劫持载入应用的样式(包括 css-in-js 样式),并对其添加该应用特有的前缀,并将组件范围外的样式映射到组件根节点的 wrapper 上,以确保该应用样式不会影响主应用,并且自身样式拥有更高优先级。 | | | | | shadowDOM | | 将应用样式隔离在 shadowDOM 中,以确保完全的隔离 | | | | | null | | 关闭样式隔离 | | | | memoryHistory | | boolean | 开启浏览器内存记录 history | 否 | false | | | true | | 开启浏览器内存记录 history,开启后子应用不会影响到主应用的路由,但网页也无法保存子应用的状态 | | | | | false | | 使用主应用路由记录子应用的 history | | | | mapping | | Record<string, string> | mapping 是一个对象,左边的 key 代表主应用的路径表达式,右边的 value 代表子应用的路径表达式。规则的匹配顺序按照 Object.keys 的顺序进行,当路由命中时后面的规则将不生效。注意:如果配置了 mapping,则会按照 mapping 的配置进行路由映射,而不会按照 base 进行路由映射。 | 否 | - | | systemjs | | string|boolean | 手动传递systemjs地址,如不传或者传true则使用默认值,传递false直接屏蔽systemjs注入。 | 否 | - | | environment | | string | 客户接入AB服务的环境类型 | 否 | default | | | default | | 默认值为 default,不做任何处理 | | | | | volc | | 表示火山云环境,如果用户接入的 AB服务基于火山云环境,此项必填。 | | | | volc | | 表示火山云环境,当前在火山云环境下必填。 | | | | | private | | 表示私有化环境 | | || private | | 表示私有化环境填。 | | |
示例
import { opInit } from '@datatester/op';
opInit({
remote: 'https://ab.resource.path/remote.js',
// 下述配置可以令主应用路由:/father/test/a/child/report 映射到微前端路由:/child/report
base: '/father/test/a';
});
MfeLoader
MfeLoader 用于加载微前端应用/页面,是一个组件,其 api 如下:
| 字段 | 子字段 | 类型 | 说明 | 是否必填 | 默认值 | | ------------- | ----------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------- | ------ | | type | | enum | 入口类型,第一次进入时默认打开的页面 | 是 | 'list' | | | 'list' | | 实验列表 | | | | | 'report' | | 实验报告 | | | | | 'create' | | 实验创建 | | | | | 'edit' | | 实验编辑 | | | | | 'draft' | | 实验草稿 | | | | appId | | number | 应用 id | 是 | - | | flightId | | number | 实验 id | 当且仅当 type 为'report'或'edit'时必填 | | | eventCallback | | (result: {type: string, flightId: number }) =>void | 事件回调方法,用于在 tester 里面某些节点操作时返回 result 给宿主页面,辅助宿主打通 AB 数据 | 否 | - | | | (type)'flight_create_success' | | 实验创建成功(开始调试) | | | | | (type)'flight_edit_success' | | 实验修改成功 | | | | | (type)'start_success' | | 实验成功开始运行 | | | | | (type)'end_success' | | 实验成功结束 | | | | | flightId | | 被操作的实验 id | | | | filters | | Object | 过滤器 | 否 | - | | | flight_ids | number[] | 需要过滤的实验 id 列表 | | | | | | | | | |
示例 (for React)
import { MfeLoader } from '@datatester/op/react';
import React, { FC } from 'react';
const MfeComponent: FC<RouteComponentProps> = () => (
<div>
<div>这是宿主应用的header</div>
<MfeLoader type="report" appId="12345" flightId="45678" templateId="12" />
</div>
);
export default MfeComponent;
示例 (for Vue)
<template>
<div>
<div class="hello">
<h1>这是宿主应用标题</h1>
<h3>op sdk show case</h3>
</div>
<mfe-loader type="report" app-id="12345" flight-id="45678" template-id="12" />
</div>
</template>
<script>
import { MfeLoader } from '@datatester/op/vue';
export default {
name: 'MfePage',
components: {
MfeLoader,
},
};
</script>
createView
createView 用于创建一个新的微前端视图,是一个函数,返回一个 promise,其有两个方法:
- render: 用于渲染视图
- unmount: 用于卸载视图
具体使用请参照如下示例
示例 for vanilla js(原生js)
// 定义注册函数
import { createView } from "@datatester/op";
export async function setupAB(element: HTMLElement) {
const view = await createView(element);
view.render({
type: "list",
appId: "12345",
});
return view;
}
// 渲染视图
const el = document.getElementById("ab")!;
const view = await setupAB(el);
// 卸载视图
view.unmount();
iframe 加载方式
IframeLoader
IframeLoader 用于通过iframe加载页面,是一个组件,其 api 如下:
| 字段 | 类型 | 说明 | 是否必填 | 默认值 | | ------------- | ----------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------- | | type | enum | 入口类型,第一次进入时默认打开的页面,enum:list (实验列表)|report (实验报告)|create (实验创建)|edit (实验编辑)|draft (实验草稿列表) | 是 | list | | appId | number | 应用id | 是 | - | | flightId | number | 实验id | 当且仅当 type 为'report'或'edit'时必填 | - | | filters | Object | 过滤器, {flight_ids: number[]},需要过滤的实验 id 列,仅在实验列表页面生效 | 否 | - | | templateId | number | 定制模版ID | 仅在iframe嵌入需要指定模版时必填 | - | | token | string | 请求open api获取token,用于打通与AB侧的鉴权 | 是 | - |
未列出iframe自身的属性
示例 (for React)
import { IframeLoader } from '@datatester/op/react';
import React, { FC } from 'react';
const IframeComponent: FC<RouteComponentProps> = () => (
<div>
<div>这是宿主应用的header</div>
<IframeLoader type="report" appId="12345" flightId="45678" templateId="12" token="xxxxxxxx" />
</div>
);
export default MfeComponent;
示例 (for Vue)
<template>
<div>
<div class="hello">
<h1>这是宿主应用标题</h1>
<h3>op sdk show case</h3>
</div>
<iframe-loader type="report" app-id="12345" flight-id="45678" template-id="12" token="xxxxx" />
</div>
</template>
<script>
import { IframeLoader } from '@datatester/op/vue';
export default {
name: 'IframePage',
components: {
IframeLoader,
},
};
</script>
DefaultViewManager
由用户自主配置URL路径
示例 (for React)
import { DefaultViewManager } from '@datatester/op/iframe';
import React, { FC, useEffect } from 'react';
const IframeComponent: FC<RouteComponentProps> = () => {
const iframeRef = useRef(null);
useEffect(() => {
const url = `https://e168-0-183tester.datarangers-onpremise.volces.com/datatester/app/1/experiment/list?abOpConfigId=1`;
if (!iframeRef.current) {
iframeRef.current = new DefaultViewManager(document.getElementById('abIframeParent') as HTMLElement, {
iframeSrc: url,
iframeAttrs: {
name: `x-rgw-dor=${document.cookie?.match('(^|;)\\s*x-rgw-dor\\s*=\\s*([^;]+)')?.pop() || ''}`,
height: '800px',
width: '100%',
style: 'border:0px',
},
});
} else {
const iframe = document.querySelector('#abIframeParent > iframe');
if (iframe) {
iframe.src = url;
}
}
}, [location.pathname]);
return <div id="abIframeParent" />;
};
export default MfeComponent;