实践分享:打造极具高扩展性的JavaScript SDK

SDK(Software Developer Kit) 是使用 FeatureProbe 服务必不可少的工具之一。SDK 能将用户的应用程序连接到 FeatureProbe 服务,根据用户的配置获取开关的结果,还能将开关的访问情况上报给 FeatureProbe,进而实现 A/B 实验的能力。

FeatureProbe 目前对外提供十余种主流开发语言的 SDK,包括用于服务端开发的 Java、Golang、Python、Rust 等,以及用于客户端开发的 JavaScript、Android、iOS 等。在之前的文章【用 Rust 开发跨平台 SDK 探索和实践】中我们曾介绍过我们选择使用 Rust 开发了跨平台语言的 Android SDK 和 iOS SDK,这样做的主要原因是:

(1)能减少人力成本和开发时间。

(2)共享一套代码,便于后期维护。

在开发 JavaScript SDK 的过程中,我们也同样采用类似的思路。JavaScript 是目前构建 Web 应用的主要语言,在此基础上产生了很多现代化的 JavaScript 前端框架,比如:React、Vue、Angular 等。近几年在国内爆火的微信小程序框架也主要使用 JavaScript 语言进行开发的。如何制作一款能支持所有前端框架使用的通用 SDK,同时在此 SDK 的基础上,能够快速地根据框架的语法特性进行上层封装,是 JavaScript SDK 的核心要求之一。

实现思路#

实现一个功能完善的 JavaScript SDK,能够在普通的 Web 前端工程中使用。在此基础上,根据框架语法特性,进一步封装其它语言的 SDK,不同语言的 SDK 分别管理和发版。

image.png

React SDK 的实现#

React SDK 在实现时将 JavaScript SDK 作为依赖项安装到工程内,主要使用了 React 的 Context API 和 Context hooks 进行上层封装,方便开发者在 React 工程中的使用。

1、使用 React 的 createContext API 创建一个上下文对象,保存开关 FeatureProbe 实例和开关结果的集合。2、使用 React 的 Context Hooks 封装若干个自定义 Hook,用于在任何组件内快速使用 FeatureProbe 实例和访问开关结果。

这里我们展示了一种以高阶组件的方式使用 React SDK。

1、将 SDK 初始化#

​使用 FPProvider 对根组件 进行初始化,初始化时传入必填参数 remoteUrl、clientSdkKey 和 user 对象等。

image.png

2、SDK 的使用#

使用 withFPConsumer 高阶组件的方式包装业务组件 ,组件内部可通过 props 属性访问 FeatureProbe 实例(client)和开关集合(toggles)。

(1)client 实例上可访问 JavaScript SDK 所有对外暴露的 API,比如 booleanValue、jsonDetail、track 等。

(2)toggles 开关集合是同一个用户在一个 clientSdkKey 环境中调用所有开关的返回结果集合,提供了另一种获取开关结果和详情的方式。

image.png

微信小程序 SDK 的实现#

相比较 React SDK,在 JavaScript SDK 上的集成微信小程序 SDK 更复杂一些,需要针对微信小程序的语法特性做一些兼容工作。主要的原因是微信小程序和普通的 Web 应用的运行环境不同,前者是在微信客户端运行,后者在浏览器环境中运行的。例如在浏览器环境中支持的 window 和 document 对象,在微信小程序中是不支持的。

下面的表格列举出了两种 SDK 的主要不同点:

JavaScript SDK 微信小程序 SDK
发送 HTTP 请求 API fetch wx.request
本地缓存 API localStorage.setItem、localStorage.getItem wx.setStorageSync、wx.getStorageSync
长连接工具库 socket.io-client wepapp.socket.io
是否支持自动上报事件 支持 不支持
UA JS/1.0.1 MINIPROGRAM/1.0.1

在代码层面,JavaScript SDK 将上述差异进行抽离,并保存在 platform 对象中,platform 对象目前包含的字段有:

UA: 标识 SDK 名称和版本;

localStorage: 本地存储对象,调用 localStorage.setItem () 方法保存数据,调用 localStorage.getItem () 方法获取数据;

httpRequest: 发送请求对象,调用 httpRequest.get () 方法发送 GET 请求,调用 httpRequest.post () 方法发送 POST 请求;

socket: 用于初始化 socket.io-client 客户端,监听开关的变更。

JavaScript SDK 导出 initializePlatform 方法,其它语言的 SDK 在初始化时可传入 platform 对象来保存配置差异部分,不传入时将使用默认值。

export function initializePlatform(options) {
  if (options.platform) {
    setPlatform(options.platform);
  }
}

以下为微信小程序 SDK 的 platform 对象构成。在发送 HTTP 请求上我们目前选择了一款开源的工具库 wefetch,方便后续支持其它的小程序 SDK,WebSocket 客户端选择了基于 socket.io 实现的 weapp.socket.io。

import wefetch from "wefetch";          // 小程序请求扩展
import pkg from '../package.json';      
const PKG_VERSION = pkg.version;        // 微信小程序 UA 信息
const io = require("weapp.socket.io");  // 基于 socket.io 实现的构建微信小程序的 WebSocket 客户端

// 基于微信小程序 API 封装的 localStorage 对象
class StorageProvider {
  public async getItem(key) {
    try {
      return wx.getStorageSync(key);
    } catch (e) {
      console.log(e);
    }
  }

  public async setItem(key, data) {
    try {
      wx.setStorageSync(key, data);
    } catch (e) {
      console.log(e);
    }
  }
}

// 基于微信小程序 API 封装的 httpRequest对象
const httpRequest = {
  get: function(url, headers, data, successCb, errorCb) {
    wefetch.get(url, {
      header: headers,
      data,
    }).then(json => {
      successCb(json.data);
    }).catch(e => {
      errorCb(e);
    });
  },
  post: function(url, headers, data, successCb, errorCb) {
    wefetch.post(url, {
      header: headers,
      data,
    }).then(() => {
      successCb();
    }).catch(e => {
      errorCb(e);
    });
  }
};

const platform = {
  localStorage: new StorageProvider(),
  UA: "MINIPROGRAM/" + PKG_VERSION,
  httpRequest: httpRequest,
  socket: io,
};

// 初始化
initializePlatform({ platform });

总结#

上面我们介绍了在 JavaScript SDK 的基础上去开发其它语言的 SDK。核心思路是首先实现一个「大而全」的通用 SDK,然后将各个语言差异的部分进行抽离,其它语言 SDK 在初始化时进行差异部分的替换。其它语言的 SDK 再根据对应的语法特性进行上层封装,底层复用 JavaScript SDK 提供的通用能力。

目前除了 JavaScript SDK 、React SDK 和 微信小程序 SDK 之外,我们正在准备 Vue SDK。如果 FeatureProbe 目前提供的 SDK 不满足您的需求,可以通过新建 issue 的方式告知我们。我们也欢迎社区伙伴能为我们贡献更多语言的 SDK,贡献 SDK 时可参考文档 SDK 贡献指南:https://docs.featureprobe.io/zh-CN/reference/sdk-contributor/。

关于 FeatureProbe#

FeatureProbe 是国内首家功能开关管理开源平台,它包含了灰度放量、AB 实验、实时配置变更等针对『功能粒度』的一系列管理操作,完全开源,可以放心直接使用。

当前 FeatureProbe 作为一个功能开关管理平台已经使用 Apache 2.0 License 协议完全开源,你可以在 GitHub 和 Gitee 上访问源码,你也可以在上面给提 issue 和 feature 等,如果你觉得我们的项目有意思,欢迎大家在 GitHub 或 Gitee 给我们点个🌟,需要大家的支持和鼓励。

GitHub: github.com/FeatureProbe/FeaturePro...

Gitee: gitee.com/featureprobe/FeatureProb...

体验环境: featureprobe.io/

本作品采用《CC 协议》,转载必须注明作者和本文链接