如何从0设计开发一款JS-SDK
一、前言
前端SDK是什么?前端SDK是为了帮助前端实现特定需求,而向开发者暴露的一些JS-API的集合,规范的SDK包括若干API实现、说明文档等
前端SDK其实很常见了,比如:
UI组件库:通过封装一系列组件,通过配置帮助开发者调用
- Antd
- ElementUI
JS类库:通过实现一类常用的方法,便于开发处理数据,也不用再考虑兼容性
- lodash
- moment
监控统计工具:通过API,来监听前端系统的报错、统计数据
- Sentry
- 百度统计等
二、开发前的设计
SDK开发其实很简单,简单到写一个函数导出就行,但在实际应用的过程中,我们要考虑很多实际情况。
1、设计原则
满足一类功能的需要
SDK一般都是为了满足一类业务的需要,所以设计之初要明确业务范围
最小可用性原则
即能用确定的方法实现,就不要再去搞复杂的内容。我理解,比如获取DOM,如果GetElementById可以实现,就不要再设计一下GetElementsByTagName、 document.querySelector等方法封装,除非有其他的开发需要无法满足。
最少依赖原则
SDK减少依赖,要避免Lodash、JQuery、Moment、Dayjs等库,尽可能自行实现必要的方法,或者引入尽量小的库。否则会导致SDK打包后过大,或者更新版本带来的兼容问题
当然一切都要根据实际情况,有些SDK是时间的各种处理,自己处理时间的成本太高,不妨引入小型的Dayjs时间库
足够稳定、向后兼容
减少BreakChange,绝不能导致载体应用崩溃,同时做好文档说明
易扩展
模块化实现方法,尽量小的封装函数,保持函数功能的单一性原则,这样就可以更好的增加SDK的能力。
根据这些原则,下面是我们做的对应操作:
2、要实现的功能
首先要明确我们写的SDK是用来做什么的?
比如我本次实现的是用户H5页面的一键登录和号码检测。
那么我们需要暴露两个实例,供其他开发者使用,为了满足易扩展的原则,我们将声明两个类,来实现(如果每个实例都很多能力,可以拆分成两个SDK也是可以的)
3、构建工具和技术选择
提供的SDK一般都要提供压缩和未压缩版本,未压缩可以用来帮助开发调用,查找问题。压缩版本可以使用在生产环境,减少http损耗。所以我们要借助构建工具来集成这部分的能力。
可供选择的压缩工具有很多:webpack、Rollup、Gulp
如果是纯类库的压缩,当然是Rollup更好,压缩更彻底
如果是有DOM和样式,那么使用webpack功能更强大
这里由于我们可能涉及到页面SDK,而且对Webpack更熟悉,所以选择Webpack
4、单元测试
SDK的设计原则有一条:足够稳定、向后兼容,最少依赖原则。
这就意味着我们要少写Bug,所以一定要引入单元测试,这里我们选择Jest,使用起来也很简单。
describe('common test', () => {test('osIsPc', () => {expect(osIsPc()).toBeBoolean(true, false);})test("isWifi", () => {expect(isWifi()).toBeBoolean(true, false);})
})
5、SDK支持的引入方式
浏览器js模块化常见的几种方式包括:amd\cmd\es6 modules\umd
1、静态资源引入
<scriptsrc="/sdk/v1/phoneserver"></script>
2、支持amd引入
define([jquery.js, lodash.js], function($, _){console.log("jquery and lodash", $, _)
})
3、支持cmd引入
define(function(require){const lodash = require('./a.js')console.log("lodash", lodash)})
4、支持es6引入
import { PhoneServer } from'phone-server-sdk'
我们直接在webpack中配置umd方式打包,然后就可以支持上面的多种引入方式
output: {path: path.resolve(__dirname, '../dist'),filename: '[name].js',library: 'Phone-JS-SDK',libraryTarget: 'umd'}
打包的库命名:Phone-JS-SDK
6、版本维护和更新
- 管理好版本号
- 记录好更新日志
SDK版本更新,每个版本都会存在差异,而用户使用的版本肯定也太一样,所以记录好版本更新日志可以减少非技术问题。
通过静态文件导出的SDK要同时部署多个版本,不能随时下线老版本。
7、其他的注意点
-
代码混淆
-
开发环境配置和代码格式
-
上传NPM
-
CDN部署
-
依赖的三方库如何打包进SDK
-
仅支持静态引入的库如何处理
-
如何全局共享库方法
-
针对有后端API交互的SDK,需要考虑
-
API要限流、限制次数、防止盗刷
-
日志监控和数据上报
三、项目实践
1、项目需要实现的能力
- 构建工具构建,配置开发环境、ts配置
- 实现类库的相关方法(版本记录、帮助命令等)
- 实现一键登录的方法(预期的功能方法)
- 实现号码检测的方法
- 单元测试
- 上传npm,支持导入
2、搭建基础架构,配置webpack。
我们选择了ts,首先配置下tsconfig.json,然后配置webpack,引入ts-lodader,通过webpack-merge自行配置生产环境和开发环境,比较简单就不重复了
module.exports = {entry: {sdk: [path.resolve(__dirname, '../src/index.ts')]},resolve: {extensions: ['.tsx', '.ts', '.js'],},output: {path: path.resolve(__dirname, '../dist'),filename: '[name].js',library: 'SDK',libraryTarget: 'umd'},module: {rules: [{test: /.ts?$/,exclude: /node_modules/,use: [{loader: 'babel-loader',options: {presets: ['@babel/preset-env'],},},{loader: 'ts-loader',options: {compilerOptions: {noEmit: false,},},},],},]}
3、实现类库的相关方法
下面是项目的主要目录结构
- src源代码
- scripts 是webpack的相关配置
- public 是用来调试和打包的目录
- tests 单元测试
LibInfo.ts 用来实现库的一些方法,比如获取版本号,帮助文档,展示依赖版本等
PhoneNumberLogin.ts 一键登录类
PhoneNumberAuth.ts 号码认证类
ajax.ts 简单封装的ajax请求
index.ts 作为入口文件
js-sdk
├─ __tests__
│ └─ utils
│ ├─ ajax.test.js
│ └─ commont.test.js
├─ public
│ ├─ index.html
│ └─ sdk.js
├─ scripts
│ ├─ webpack.base.config.js
│ ├─ webpack.dev.config.js
│ └─ webpack.prod.config.js
├─ src
│ ├─ lib
│ │ ├─ LibInfo.ts
│ │ ├─ PhoneNumberAuth.ts
│ │ ├─ PhoneNumberLogin.ts
│ │ └─ Init.ts
│ ├─ utils
│ │ ├─ ajax.ts
│ │ ├─ common.ts
│ │ └─ interface.ts
│ └─ index.ts
├─ Readme.md
├─ index.d.ts
├─ jest.config.js
├─ package.json
├─ tsconfig.json
└─ yarn.lock
4、实现SDK的接口
1、在调用之前,我们需要引用第三方库,而且是md5加密的(如下),无法直接下载本地使用,所以考虑直接插入head中

exportconst scriptInit = (src: string, callback?: Function) => {const script:any = document.createElement('script'),fn = callback || function(){};script.type = 'text/javascript';//IEif(script.readyState){script.onreadystatechange = function(){if( script.readyState == 'loaded' || script.readyState == 'complete' ){script.onreadystatechange = null;fn();}};}else{//其他浏览器script.onload = function(){fn();};}script.src = src;document.getElementsByTagName('head')[0].appendChild(script);}
2、我们以实现意见登录号码为例,新建PhoneNumberLogin.ts
const loginPhoneUrl = `http://test.com`exportclass PhoneNumberLogin {constructor(options:AppInfo){this.Init()}private Init(){// 引入第三方依赖的scriptscriptInit(loginPhoneUrl)} // 处理一键登录的接口逻辑public LoginApp(options){return options}}
这样我们每一个小的功能点都放在一个类中,不对外的设置为私有方法,对外的可以设置为公共方法,其他的通过引用就可以让SDK保持良好的可扩展性。
3、在index.ts中抛出方法
export * from'./lib/PhoneNumberLogin.ts'
4、在项目中使用
script导入,一般都需要申请域名,那么就需要考虑容灾,防止一台机器挂掉,服务不可用,一般考虑CDN部署
const { PhoneNumberLogin } = Phone-JS-SDK
const PhoneServer = new PhoneNumberLogin()
ES6 Modules导入
const { PhoneNumberLogin } from"Phone-JS-SDK"
const PhoneServer = new PhoneNumberLogin()
5、上传NPM
接着我们发布下npm,一个JS-SDK就完成了。
登陆npm仓库,没有的话去注册一个,地址[2]
npm login
选择一个中意的SDK名字,查一下是否存在,这里我们起个名字Phone-JS-SDK
执行npm version patch && npm publish --registry=https://registry.npmjs.org,然后就发布成功了。
相关文章:
如何从0设计开发一款JS-SDK
一、前言 前端SDK是什么?前端SDK是为了帮助前端实现特定需求,而向开发者暴露的一些JS-API的集合,规范的SDK包括若干API实现、说明文档等 前端SDK其实很常见了,比如: UI组件库:通过封装一系列组件ÿ…...
linux实现rsync+sersync实时数据备份
1.概述 rsync(Remote Sync) 是一个Unix/linux系统下的文件同步和传输工具 2.端口和运行模式 tcp/873 采用C/S模式(客户端/服务器模式) 3.特点 可以镜像保存整个目录和文件第一次全量备份(备份全部的文件),之后是增量备份(只备份变化的文件) 4. 数…...
【计算机网络】计算机网络协议、接口与服务全面解析——结合生活化案例与图文详解
协议、接口与服务 导读一、协议1.1 定义1.2 组成 二、接口三、服务3.1 定义3.2 服务与协议的区别3.3 分类3.3.1 面向连接服务于无连接服务3.3.2 可靠服务和不可靠服务3.3.3 有应答服务和无应答服务 结语 导读 大家好,很高兴又和大家见面啦!!…...
51c自动驾驶~合集26
我自己的原文哦~ https://blog.51cto.com/whaosoft/11968755 #大模型/Sora/世界模型之间是什么关系 1 什么是大模型 人工智能大模型(Artificial Intelligence Large Model,简称AI大模型)是指具有庞大的参数规模和复杂程度的机器学习模…...
【汽车传感系统架构:借助传感获取安全】
为了将车辆自动化提升到一个新的水平,设计人员研究了 LiDAR 等传感器选项的权衡,并着眼于传感系统架构。 本文引用地址:https://www.eepw.com.cn/article/202503/468584.htm 每年,约有 120 万人死于道路交通事故,还有…...
【NUUO 摄像头】(弱口令登录漏洞)
漏洞简介:NUUO 是NUUO公司的一款小型网络硬盘录像机设备。 NUUO NVRMini2 3.0.8及之前版本中存在后门调试文件。远程攻击者可通过向后门文件handle_site_config.php发送特定的请求利用该漏洞执行任意命令。 1.Fofa搜索语句: 在Fofa网站,搜索&…...
论文阅读笔记:Denoising Diffusion Probabilistic Models (3)
论文阅读笔记:Denoising Diffusion Probabilistic Models (1) 论文阅读笔记:Denoising Diffusion Probabilistic Models (2) 论文阅读笔记:Denoising Diffusion Probabilistic Models (3) 4、损失函数逐项分析 可以看出 L L L总共分为了3项…...
【设计模式】抽象工厂模式(含与工厂方法模式的对比)
本期我们来学习一下设计模式之抽象工厂模式,在软件开发中,工厂模式 和 抽象工厂模式 都用于创建对象,但它们的应用场景和实现方式有所不同。本文将基于 C 代码,分析抽象工厂模式的实现,并对比其与工厂方法模式的区别。…...
消息队列保证最终一致性的优势
消息队列保证最终一致性的优势 使用消息队列(如Kafka、RabbitMQ等)来实现MySQL和Redis之间的最终一致性,具有以下几个显著优势: 1. 解耦系统组件 降低系统耦合度:生产者(MySQL更新)和消费者&…...
IDEA转战Trae AI IED配置
Trae Ai 的前身是vscode IDEA转战Trae AI IED配置 1.安装java相关的插件 2、安装spring相关的插件 3.配置maven环境 打开 Trae AI IDE -> 首选项 -> 设置 -> Editor 设置 ⚠️配置方式有两种 setting.json文件中直接编辑(推荐)界面设置 方案…...
再学:区块链基础与合约初探 EVM与GAS机制
目录 1.区块链是什么 2.remix 3.账户 4.以太坊三种交易 5.EVM 6.以太坊客户端节点 7.Gas费用 8.区块链浏览器 1.区块链是什么 只需要检验根节点 Merkel根是否有更改,就不用检查每个交易是否有更改。方便很多。 2.remix 3.账户 如果交易失败的话&…...
Nextjs15 - middleware的使用
nextjs 官方文档(current branch 对应如下文档) Middlewarepath-to-regexp 本专栏内容均可在Github:test_05/Middleware 找到 一、middleware 基本使用 中间件允许您在请求完成之前运行代码。然后,根据传入的请求,您…...
PHP If...Else 语句详解
PHP If...Else 语句详解 引言 PHP 是一种流行的服务器端脚本语言,常用于开发动态网站和应用程序。在 PHP 编程中,条件语句是编程逻辑的基础,其中 if...else 语句是最基本且最常用的条件语句之一。本文将详细介绍 PHP 的 if...else 语句&…...
Django之旅:第六节--mysql数据库操作增删改查(二)
前提条件(models.py已经设置好): from django.db import mmodelsclass UserInfo(models.Model):namemodels.CharFIeld(max_length32)passwordmodels.CharFIeld(max_length64)#agemodels.IntegerFIeld()操作数据语法(在views.py文件࿰…...
【SUNO】【AI作词】【提示词】
仿写歌词提示词模板(升级版) 一、仿写目标 风格定位 音乐风格: [填写目标风格,如:民谣/流行/古风/电子/爵士等]参考案例:如《成都》的叙事民谣,《孤勇者》的励志流行。 情感基调: […...
边缘计算 vs. 云计算,谁才是工业物联网的未来?
前言 在物联网(IoT)飞速发展的今天,边缘计算正在彻底改变数据的处理、存储和分析方式。传统的IoT设备数据通常需要发送到云端进行处理,但随着设备数量的激增,这种模式在延迟、带宽和安全性方面暴露出诸多局限。边缘计…...
【Qt】QByteArray详解
QByteArray 是 Qt 框架中用于处理原始字节数据的核心类,其实质可以概括为以下几点: 1. 底层数据结构 • 连续内存块:存储一段连续的字节数据(char*),类似 std::vector<char>,但针对 Qt 框…...
leetcode.189.轮转数组
第一次全反转,第二次反转前k个,第三次反转后n-k个 需要注意的是向又轮转k个时,如果超出数组长度,要对其进行取模运算才是正确的向右轮转个数 class Solution { private:void rotate(vector<int>& nums,int start,int …...
OCR 识别案例
OCR 识别案例 注意点:输入图像尺寸比例尽量和参与模型训练的数据集比例相似,识别效果会更好。 1、pytesseract Pytesseract是一个Python的光学字符识别(OCR)工具,它作为Tesseract OCR引擎的封装,允许你在…...
微信 MMTLS 协议详解(五):加密实现
常用的解密算法,对称非对称 加密,密钥协商, 带消息认证的加解密 #生成RSA 密钥对 void GenerateRsaKeypair(std::string& public_key,std::string& private_key) {RSA* rsa RSA_new();BIGNUM* bn BN_new();// 生成 RSA 密钥对BN_s…...
Mybatis配置文件解析(详细)
引言 在了解Mybatis如何帮助客户进行数据的存取后,便对Mybatis的配置文件起了兴趣,在查阅官方文档后,总结了平时能用到的配置,希望能对大家有帮助 1.核心配置文件 主要是指Mybatis-config.xml中 其包含了会深深影响Mybatis行为…...
有额外限制的 bellman_ford 算法
题目链接 1.有限制的 B e l l m a n _ F o r d Bellman\_Ford Bellman_Ford 时间复杂度: O ( N ∗ M ) O(N*M) O(N∗M) 在传统的 B e l l m a n _ F o r d Bellman\_Ford Bellman_Ford 中,可以处理边数不大于 K K K 条边的最短距离 但我们只要加一条限制(实际…...
深度剖析 Spring 源码 性能优化:核心原理与最佳实践
深度剖析 Spring 源码 & 性能优化:核心原理与最佳实践 🚀 Spring 框架 作为 Java 生态的核心技术,广泛应用于企业级开发。但很多开发者只会“用”Spring,而不深入其内部原理,导致无法高效排查问题 & 进行性能优…...
【BFS】《单源、多源 BFS:图搜索算法的双生力量》
文章目录 前言单源BFS例题一、迷宫中离入口最近的出口二、 最小基因变化三、单词接龙四、为高尔夫比赛砍树 多源BFS例题一、 01 矩阵二、飞地的数量三、地图中的最高点四、地图分析 结语 前言 什么是单源、多源BFS算法问题呢? BFS(Breadth - First Sear…...
【2025】基于springboot+vue的医院在线问诊系统设计与实现(源码、万字文档、图文修改、调试答疑)
基于Spring Boot Vue的医院在线问诊系统设计与实现功能结构图如下: 课题背景 随着互联网技术的飞速发展和人们生活水平的不断提高,传统医疗模式面临着诸多挑战,如患者就医排队时间长、医疗资源分配不均、医生工作压力大等。同时,…...
【前端】原生项目与框架项目区别
不定期更新,建议关注收藏点赞。 使用 HTML CSS JS 和 Vue 或 React 开发的项目各有其优势与不足,适用于不同的场景。目前基本上都采用框架, 总结 何时选择 HTML CSS JS: 适用于 小型项目、简单静态页面、不需要复杂交互 或 …...
STM32基础教程——PWM驱动舵机
目录 前言 技术实现 原理图 接线图 代码实现 内容要点 PWM基本结构 开启外设时钟 配置GPIO端口 配置时基单元 初始化输出比较单元 调整PWM占空比 输出比较通道重映射 舵机角度设置 实验结果 问题记录 前言 舵机(Servo)是一种位置ÿ…...
ThreadLocal详解与高频场景实战指南
ThreadLocal详解与高频场景实战指南 1. ThreadLocal概述 ThreadLocal是Java提供的线程本地变量机制,用于实现线程级别的数据隔离。每个访问该变量的线程都会获得独立的变量副本,适用于需要避免线程间共享数据的场景。 特点: 线程封闭性&a…...
odata 搜索帮助
参考如下链接: FIORI ELement list report 细节开发,设置过滤器,搜索帮助object page跳转等_fiori element label 变量-CSDN博客 注:odata搜索帮助可以直接将值带出来,而不需要进行任何的重定义 搜索帮助metedata配置…...
RK3588开发笔记-RTL8852wifi6模块驱动编译报错解决
目录 前言 一、问题背景 二、驱动编译 总结 前言 在基于 RK3588 进行开发,使用 RTL8852 WiFi6 模块时,遇到了一个让人头疼的驱动编译报错问题:“VFs_internal_I_am_really_a_filesystem_and_am_NoT_a_driver, but does”。经过一番摸索和尝试,最终成功解决了这个问题,在…...
