专栏名称: 前端从进阶到入院
我是 ssh,只想用最简单的方式把原理讲明白。wx:sshsunlight,分享前端的前沿趋势和一些有趣的事情。
目录
相关文章推荐
湖北经视  ·  部分武汉药店出售华为WATCH ... ·  9 小时前  
湖北经视  ·  69岁周润发,传新消息 ·  昨天  
湖北经视  ·  初步核查29人失联,灾害原因公布 ·  2 天前  
湖北经视  ·  AI生成图被商用,侵权吗?武汉一法院判了 ·  3 天前  
51好读  ›  专栏  ›  前端从进阶到入院

如何开发一款 JSSDK,全面考虑到设计、结构、发布更新等方面

前端从进阶到入院  · 公众号  ·  · 2024-07-02 08:00

正文

本文作者系360奇舞团前端开发工程师


JSSDK的定义与分类
什么是JSSDK

SDK是 Software Development Kit (软件开发工具包)的缩写, JSSDK 是为了帮助前端实现特定需求,而向开发者暴露的一些 JS-API 的集合,开发者可以通过它在网页中集成和使用某些特定的功能,例如社交分享、地图服务、支付功能等.它通常包括一下模块:

  1. JavaScript 库:这是 JSSDK 的核心部分,包含了一系列预先编写好的 JavaScript 代码,这些代码实现了一些特定的功能,如用户认证、数据分析、社交分享等。
  2. API 文档:这部分文档详细描述了如何使用 JSSDK 中的各个功能。它通常会包含函数和方法的列表,以及如何使用这些函数和方法。
  3. 示例代码 :这部分代码展示了如何在实际项目中使用 JSSDK 。通过阅读和运行示例代码,开发者可以更好地理解如何使用 JSSDK
JSSDK的分类

JSSDK 的分类主要取决于它们提供的功能和服务。通常根据其功能不同分为: UI组件库 JS工具库 分析统计SDK 社交媒体SDK

  • UI组件库 :通过封装一系列组件,通过配置帮助开发者调用,实现一些UI效果,例如: Antd ElementUI Vant Bootstrap
  • JS类库 :通过实现一类常用的方法,便于开发处理数据,也不用再考虑兼容性,常用的如: lodash moment axios jQuery
  • 监控统计工具 :通过API,来监听前端系统的报错、统计数据,以及数据上报等,例如: Sentry 、百度统计、 Google Analytics JSSDK
  • 其他第三方的SDK :微信SDK、支付宝SDK、新浪微博SDK, Facebook JSSDK

如何设计JSSDK

设计SDK要遵循的原则
  1. 单一职责原则 :SDK一般都是为了满足一类业务的需要,所以设计之初要明确业务范围,如果功能过于复杂,可以拆改成几个独立的SDK,在主SDK中引入相关逻辑就OK了,这样便于功能解耦和测试。
  2. 最小可用、最少依赖性原则 :能用确定的方法实现,就不要再去搞复杂的内容。SDK要减少依赖,一些工具库能不用就不用。尽可能自行实现必要的方法,或者引入尽量少的库。否则会导致SDK打包后过大,或者更新版本带来的兼容问题。
  3. 稳定性原则 :保持SDK足够的稳定性,一方面要保持API方法的稳定,另一方面在设计API的入参时,参数要用对象类型,这样便于后续扩展添加更多参数。如果SDK有升级要考虑兼容旧版本。新功能要新增API,旧的API不要删除。
  4. 易用性原则 :要满足易用性原则,首先要有简洁的API,明确的方法注释、文档跟示例代码很重要,不管SDK写的多漂亮,使用者首先接触的是接入文档,然后是覆盖所有API的示例代码,一个好的实例代码能起到事半功倍的效果。
语言与构建工具选择
  1. 语言的选择 语言无非是选择 TS 还是 JS ,这里推荐使用 TS 来编写SDK代码因为相比 JS 而言他有如下优势:
  • 类型系统 TypeScript 的最大特点就是它的类型系统。这个类型系统可以在编译阶段捕获许多常见的错误,如类型错误、未定义的函数或属性等,从而提高代码的质量和可维护性。
  • 更好的工具支持 :由于 TypeScript 的类型信息, IDE 和编辑器可以提供更好的代码补全、自动提示等功能。
  1. 构建工具的选择 推荐使用 Rollup 来作为SDK项目的打包构建工具
  • Rollup 的配置通常比 Webpack 更简单,更易于理解。这对于新手或者希望快速开始项目的开发者来说是一个优点。
  • 更好的 Tree-shaking Rollup Tree-shaking 功能通常比 Webpack 更有效。 Tree-shaking 是一种只包含实际使用的代码,而去除未使用代码的优化技术。这可以帮助减小最终打包文件的大小。
  • Rollup 是以 ES6 模块标准为中心设计的,这使得它在处理 ES6 模块时更加高效。
  • 适合库的打包:由于 Rollup 的特性,它通常更适合用于打包库(library)或者工具,而 Webpack 则更适合用于打包应用( application )。

SDK核心功能的实现

需求

假设我们开发一款问卷投放SDK,满足问卷的自动投放、代码控制投放、事件触发投放、问卷回收等逻辑。注意单一职责原则的应用,只做问卷的投放、回收逻辑。问卷里面内容展示,以及内部相关逻辑不涉及。

项目结构
`src`: 源代码
  • api/index.t s: 网络请求的API封装
  • core/index.ts :核心入口文件
  • core/dependencies.ts :核心逻辑实现文件
  • style/index.css : 样式文件
  • types/index.ts : 声明的类型文件
  • utils/constants.ts : 常量文件
  • utils/http.ts : 网络请求封装库
  • utils/index.ts : 工具函数
  • utils/pv.ts : 路由监听处理函数
API的设计
`SDK API`的设计根据功能分为两大类:`生命周期方法`与`实例方法`.
  • 生命周期方法:主要是SDK的生命周期回调函数:从init初始化方法,问卷的打开与关闭回调。
  • 实例方法:负责具体的业务实现

需要注意的是在设计对外API时,每个API都要有方法执行完成后回调,便于用户执行后续逻辑。

项目架构
  • Index 入口文件里面主要是对外的 SDK生命周期方法与实例方法。首先调用initQaSDK,完成问卷SDK实例的创建, 里面主要包含:
  1. 单例模式来创建实例
  2. 接受用户的必要入参与参数校验
  3. 设置路由变化监听
  4. 完成与服务端的对接逻辑
  • Dependencies :里面是核心逻辑层的实现。单独抽出一个文件的目的是,便于方法的复用。再下面是对 Dom 的操作: Dom 元素的创建、更新、与移除逻辑,最底下是依赖语言与构建工具
rollup.config.mjs
import ts from "rollup-plugin-typescript2";
import dts from "rollup-plugin-dts";
import commonjs from '@rollup/plugin-commonjs'
// es6 转 es5
import babel from '@rollup/plugin-babel'
// 模块自动导入并导出
import { importExportPlugin } from 'rollup-plugin-import-export'
import postcss from 'rollup-plugin-postcss'// 处理css 的插件
// 代码压缩
import terser from '@rollup/plugin-terser'
// 配置环境变量
import replace from 'rollup-plugin-replace';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import json from '@rollup/plugin-json';

import path from "path"
import { fileURLToPath } from 'url'
const __filenameNew = fileURLToPath(import.meta.url)
const __dirnameNew = path.dirname(__filenameNew)

const isProduction = process.env.NODE_ENV === 'production';

const API_URL_MAP = {
    production: 'https://prod.***',
    pre: 'https://pre.*****' ,
    development: 'https://dev.***'
};

function getEnvApiUrl({
    return API_URL_MAP[process.env.NODE_ENV] || API_URL_MAP.production;
}

export default [
    {
        //入口文件
        input: './src/core/index.ts',
        output: [
             //打包esModule
            {
                file: path.resolve(__dirnameNew, "./dist/index.esm.js"),
                format: "es"//输出类型 ESM 支持通过import export引入
                sourcemap: false,
            },
             //打包common js 支持 require exports 引入
            {
                file: path.resolve(__dirnameNew, "./dist/index.cjs.js"),
                format: "cjs",
                sourcemap: false,
            },
            //打包 AMD CMD UMD global 引入 将依赖包注入到全局变量中 支持






请到「今天看啥」查看全文