开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情
什么是 SDK?
SDK(Software Development Kit)即 软件开发工具包 ,就是帮助我们开发出软件的工具集合,除了代码之外,一般还要搭配文档、示例等。
除了 SDK 以外还有 JDK(Java Development Kit),前缀不重要,重要的是 DK(Development Kit),就是开发工具包,对于前端来说 SDK 就是 npm 包,某个有专门功能的包,但是 SDK 的概念要早于 npm 包,而且 JS SDK 一般都会当 npm 包部署
与 npm 包的区别
非要说两者有什么区别的话,就是 SDK 是提供方的一种服务,通常是封装了提供方的 Open API,然后 SDK 通过暴露 JS API 给外部用户使用,比如七牛云提供的 qiniu/js-sdk 里面就包含七牛云存储官方 API
PS: 有关讨论
适用场景
一个应用的JS-SDK大概可以分为以下三种
- 分析与统计工具(类似百度统计的js-sdk工具)
- 嵌入式类(类似 widget、视频播放器(video)的 sdk)
- Web的API集合(类似微信官方的js-sdk工具)
使用
这里还是用七牛云提供的 qiniu/js-sdk 做示范
import * as qiniu from 'qiniu-js'
const observable = qiniu.upload(file, key, token, putExtra, config)
const subscription = observable.subscribe(observer) // 上传开始
// or
const subscription = observable.subscribe(next, error, complete) // 这样传参形式也可以
subscription.unsubscribe() // 上传取消
就是和 npm 包的使用一致,没啥大的区别
本来想用微博的 sdk 包的,但没想到又要审核!
手写 JS SDK
国内很多提供第三方登录的服务商,比如微博,提供给网站的是 SDK,而 github 的 OAuth 就是纯 API 或者纯接口,而这次手写的 JS SDK 就是给 github 的登录时自动加上 state(一个 github 防 csrf 攻击的参数)
你可以在线查看所有的源代码
SDK 在设计要求以下
- 最小可用性原则: 也就是没有必要的功能/代码尽量不额外添加, 使代码达到最简
- 最少依赖原则: 也就是没有必要的依赖坚决不添加, 以达到最低限度的外部依赖
- 易扩展: 插件化,最大限度支持扩展和自定义
- 稳定性: 绝不能导致宿主应用崩溃,向后兼容, 可测试
关于 GitHub 的第三方登录可以查看这篇文章
Github 是跳转登录,其 url 如下
GET https://github.com/login/oauth/authorize
参数
其中 state 是作为防止 csrf 攻击存在的,但是关于它的处理上为了让开发不去过于纠结,所以可以单独抽取出来,这就是我们设计的 SDK 的基本逻辑,如下
const md5 = require("blueimp-md5");
const login = async ({ client_id, redirect_uri }) => {
const timestamp = new Date().getTime();
const state = md5(timestamp);
localStorage.setItem("state", state);
window.location.href = `https://github.com/login/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&state=${state}`;
};
顺便给 state 加上一个 md5
然后重定向之后的操作也由我们的 SDK 完成
const checkLogin = (callback) => {
/**
* 获取URL参数
* @param 参数名
*/
function getQueryString(name) {
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
const r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
}
function getLocalState() {
return localStorage.getItem("state");
}
const code = getQueryString("code");
const state = getQueryString("state");
if (code && state === getLocalState()) {
callback(code);
}
};
然后使用上就可以调用这两个 API
const GithubSDK = require("../../csrf-github-oauth-sdk/index.js");
// redirect_uri 处页面执行检测
GithubSDK.checkLogin((code) => {
// 成功后获取 token
// ...
});
// ...
window.handleGithubLoginClick = () => {
GithubSDK.login({
client_id: "b351931efd1203b2230e",
redirect_uri: "http://localhost:8080/login.html",
});
}
从导入来说和正常 npm 包一致,但是又和平常的业务代码不同,因为并不需要我们自己去写 Ajax,而是封装在了我们开发的 SDK 中