npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@datatester/op

v0.2.1

Published

## 介绍

Downloads

190

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;