说说 JS SDK

Tags: js

SDK 是什么?简单说一般包含一个或多个API、文档、依赖的一些开发调试工具,提供给第三方开发者使用的一些功能集合。可能在上个时代,开发人员最广为熟知的 SDK 应该是各大操作系统提供的开发包、硬件集成工具包等。现在是互联网时代、随着一些平台型企业、用户量很大的 APP 崛起,移动和 Web 平台的 SDK 也变为主流。国内最典型的比如 微信、微博、支付宝的 SDK,已经成为大多数网站或商户的必备依赖。

从功能上看,常用 SDK 的复杂度一般不算高、主要提供一些常见刚需功能,比如登录、分享、支付、人脸识别等。当然这不能一概而论,比如很多云平台的 SDK 功能就更多更复杂,甚至已经超出了 SDK 这个范畴。从结果上看,SDK 除了要达到“易用”、“可扩展”、“兼容性” 等通用的软件标准外,由于天生需要运行在第三方软件环境里,额外必须要确保“独立可运行”、“不与其他代码产生冲突”、“性能优良”等结果。

上边泛泛而谈的介绍过后,这里针对 js SDK 从几个方面讨论下如何做。

运行环境

首先 js 的运行环境可以有很多,服务端 js (node) 跟 Java 类似、运行在纯粹定制化的环境里。服务端的 SDK 大多也是比较纯粹的功能开发、相对来说是比较“简单”的;另外使用方式也较统一、比如大都需要申请 AccessKey / SecretKey 再调用,这里不具体讨论。

而前端 js 比较统一的运行在各种浏览器或 Webview 里,相应 SDK 表现形式也就是 js 或 css,在这些环境里运行时会遇到哪些问题?我们详细列举下:

  • 需要兼容的浏览器类型和版本?
    • 首先不太可能兼容所有浏览器,这就需要根据需求、给出最低的兼容版本和相应理由。
  • 代码在用户 html 文件中如何引入?
    • 一般通过独立的 js / css 文件或者是内联引入。
  • 在 html 的什么地方引入?
    • 前提需要仔细了解 html 的渲染方式、浏览器对资源的加载方式。
    • 比如放在 head 标签里、应该放在最上边还是下边,js 和 css 谁先谁后、按什么顺序放置。
    • script 标签是否需要使用 async charset 等标记。
  • 是 一次性 or 分多次 引入?
    • 比较理想的方式是,一个页面一次性引入 SDK、并且只运行一次,但实际情况往往更复杂。
    • 像功能复杂的 vm 页面 (Java 后端 velocity 渲染,比如支付宝收银台) 都是由“一个个模块”一起拼成。而不同模块、是由不同人(甚至不同团队)开发,这就会有多次引入 SDK 的需要。
  • 一个页面多次引入 SDK 需要考虑哪些问题?
    • 由多人参与开发的多个模块拼成的页面,最难保障的是代码异常报错问题。上一个模块报错、很可能会直接导致下一个模块不可用、甚至整个页面挂掉。
    • 也可能会有需要“异步加载”的脚本,这又涉及到浏览器执行异步脚本的兼容问题。
    • 一个页面(包括现在流行的 SPA 应用)可能会多次引入相同的 SDK、会遇到经常难以避免的命名冲突问题。所以,从设计上一开始就要考虑 是否全局唯一、是否支持多实例共存

总之、需要充分了解你的代码运行环境,这是在编写 SDK 之前要做的最基本准备。

开发方式

环境问题很大程度上决定 SDK 的整体架构方式。接下来就是开发过程可能遇到的问题,仍然会有很多、也分几类讨论:

  • API 该如何设计?
    • 其实 SDK 本身就是一个前端组件,一定要慎重考虑 API 的设计。因为业务相关性强、不止要满足当前业务需求,更需要考虑到业务可能的演变、而能做出面向未来的前瞻性设计。这点非常重要,如果设计上没有扩展性、可能下个版本就面临的是难以兼容的破坏性更新,对用户和业务都是巨大的成本。显然 SDK 的设计,往往比业务无关的纯前端组件更加复杂。
  • 全局变量,唯一性?
    • 是否需要有注册到 window 上的全局变量?当然是尽量不要有。
    • 怎么确保唯一性?可能需要随机数来生成有唯一性的接口,或者维护一个实例队列。
  • 是否使用 iframe?
    • 为了最大限度地不影响宿主环境,一般有 UI 的 SDK 很多都会用 ifame,比如网站里的第三方评论框。但是 iframe 总是会涉及到“跨域通信、高度动态变化”等非常不便的问题需要解决。
    • 那么 Web Component 的 Shadow Dom 是否可作为替代方式?现阶段可行性仍不够。
  • 怎么确保不与宿主代码产生冲突?怎么确保足够小的体积和好的性能?
    • 总的办法就是:使用原生 js 进行开发,不依赖 react / angular / vue 等大型框架。甚至一些 lodash / jquery 等功能库都不能依赖。
  • 一些 UI 组件该如何写?
    • 用原生 js 来做 UI 组件的成本是比较高的,可能一个 button 还比较简单、但常用的 modal 等更复杂组件就麻烦了。
    • 这样看来,一套应用于 sdk 的原生 UI 组件库和功能库,也是非常有必要的;但这又带来了新的维护成本。
  • 代码关键数据埋点、异常监控问题?
    • 不论是数据埋点或异常监控,都需要有上报接口,这些会带来更多的风险。比如某些 SDK 用户限制第三方域名访问、跟宿主本身的埋点监控的可能冲突。
    • 但没有这些、放任其裸奔,稳定性便得不到保障;至于怎么做、只能具体问题具体分析了。
  • 文档问题?
    • 和普通代码文档的主要区别,就是 SDK 需要详细写好用户“使用文档”。这和 SDK 本身代码开发文档应该区别对待,最好放到不同文件里。

另外,一套 sdk 如果需要同时支持 mobile 和 pc 端,核心重逻辑都相同、区别只是在交互方式上,那么代码应该怎么维护?当然最好是放到一个仓库里维护,共享能复用的组件、有差别的地方分别放到 /m/pc 的目录里,在构建时、需要写脚本生成不同平台的 dist 代码。如果不是单页应用,而是多页部署、那还需要判断 URL 里区分 m 或 pc 来分别加载不同页面即可。

示例

支付宝登录安全验证 sdk 如下图

这个 sdk 就是使用原生 js 开发,除了依赖轻量级的 reqwest 请求库和 i18n 国际化处理库外、其他无任何三方依赖。另外必须要能支持灵活部署、避免和宿主代码冲突,也要确保体积不能大、性能不能差。

总结

特别是对于比较复杂的 SDK、综合开发难度其实远大于普通的业务开发。不过,不管前端还是后端 SDK,面临的问题可能各不相同,但解决的思路往往能互相借鉴,希望后续能有更多深入思考和总结。

最近文章

2024-02-15 » 字节监控之旅
2024-01-06 » 如何做一个好的管理者
2023-12-23 » E2E测试实践