专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

前端工程化 → 深入SDK架构设计

ins518 2024-09-14 08:42:12 技术文章 20 ℃ 0 评论

前置知识

SDK 的全称是 Software Development Kit,翻译过来是软件开发工具包,这是一种被用来辅助开发某类软件而编写的特定软件包,其主要是为宿主系统提供服务的。

接口设计原则

设计初衷

  • 可以减少人力成本和开发时间
  • 共享一套代码,便于后期维护

最牛批的实现方式是开发一套可以支持所有前端框架使用的通用SDK(如React、Vue、angular、小程序等)(可以采用不同语言的SDK分别管理和发版),同时在此SDK的基础上,可以快速地根据框架的语法特性进行上层封装,是JavaScript SDK的核心要求之一;

设计理念

设计SDK的方式主要取决于SDK的额最终用途,如提供给网页调用和提供给服务端调用是不一样的,当然也是有一些明显的共用原则,主要有两个基本的原则:

设计原则

SDK内容包括

SDK架构设计



let checkCanSessionStorage = function () {
let mod = "modernizr";
try {
sessionStorage.setItem(mod, mod);
sessionStorage.removeItem(mod);
return true;
} catch (e) {
return false;
}
};
import SDKForA from 'SDK/dist/modern/components/SDKForA';
// 组件导出的npm包/编译后产物打包的目录/ESM 规范的打包路径/要引入的组件
    • UMD是希望提供一个前后端跨平台的解决方案(支持AMD、CommonJS模块化方式和全局变量的方式来导入和导出模块),是一种通用的模块化规范,旨在兼容不同环境;
      对于「调用方」来说,在安装直接依赖库时也会安装其dependencies中的所有SDK,一般情况下会和其他依赖同级,当有「同名且冲突、或版本不同时」的依赖会直接安装到「SDK/node_modules下」,即所有依赖会平级设置;完全理解各种dependencies
    • 在SDK设计时不可能将几种模块化都分别实现一遍,一般采用rollup来编译SDK源码,从而满足三种规范的代码;
// package.json
{
"name": "@lbxin/build-laugh",
"version": "1.0.0",
// "main": "src/index.js",
"main": "dist/cjs/index.js",
"module": "dist/es/index.js",
"files": ["dist"],
"scripts": {
"build":"rm -rf ./dist && rollup -c build/config/rollup.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"rollup": "^2.55.1"
}
}


// src/config/rollup.config.js

import { resolve } from 'path'
import { name,dependencies } from '../package.json'

const FORMAT = {
'ES': 'es',
'CJS': 'cjs',
'UMD': 'umd'
}

const base = {
input: resolve(__dirname, '../src/index.js'),
external: Object.keys(dependencies), //不用处理dependencies中相关的import逻辑
};

const output = function (format) {
return {
name,
dir: resolve(__dirname, `../dist/${format}`),
// format 参数,决定输出需要满足哪一种模块化规范
format,
}
}

export default [
{
...base,
output: output(FORMAT.ES),
},
{
...base,
output: output(FORMAT.CJS),
},
{
...base,
output: output(FORMAT.UMD),
}
]
      • UND内部逻辑浅析
      • 先判断是否支持Node模块格式(exports是否存在)
      • 再判断是否支持AMD(define是否存在)
      • 前两个都不存在则将模块公开到全局(window或global)
//静态资源引入
<script src="/sdk/v1/wpkReporter"></script>
// ES Module(使用import和export关键字来导入和导出模块,支持静态分析(在编译时进行模块依赖的静态分析,有更好的性能和可靠性))

import wpkReporter from 'wpkReporter'

// CommonJS(是同步加载的,主要用于服务端开发,通过module.exports导出模块、require函数加载模块)
const wpkReporter = require('wpkReporter')

// AMD,requireJS引用
//AMD(异步模块定义,主用于浏览器,遵循依赖前置原则,使用define函数定义模块、require函数加载模块)
define([jquery.js, lodash.js], function($, _){
console.log("jquery and lodash", $, _)
})
//CMD(通用模块定义,用于浏览器或node中,遵循依赖就近原则,使用define函数定义模块、require函数加载模块)
define(function(require){
const lodash = require('./a.js')
console.log("lodash", lodash)
})


require.config({
paths: {
"wpk": "https://g.alicdn.com/woodpeckerx/jssdk/wpkReporter.js",
}
})
require(['wpk', 'test'], function (wpk) {
// do your business
})

JS-SDK在前端中的案例

  • UI组件库
  • 性能监控工具,如阿里的arms,岳鹰前端监控SDK等
  • 统计分析工具
  • 智能验证工具SDK
  • TRTC Web SDK新架构设计

SDK优劣分析

JS-SDK实现

  • 前端SDK的核心就是API接口,该方式以函数的形式提供所需的功能,开发人员可以通过调用接口函数来实现相应的功能
var SDK = {
// 接口函数1
showMessage: function(message) {
alert(message);
},
// 接口函数2
showConfirm: function(message) {
return confirm(message);
}
};
  • 代码封装

前端SDK可以根据功能模块进行模块化封装,使得代码更易于管理和维护;通过将SDK代码进行重构,让SDK可以更加容易拓展、尽量减少模块之间的耦合,使得各个功能模块更加独立,甚至可以做到轻松的添加和删除模块而不会对其他的模块有影响。
模块化主要是为了方便SDK的开发者适应各种需求的变化,而插件化则主要是为了更方便SDK的使用者;插件化就是指SDK开发者可以根据使用者需求提供接入相对应功能的差异化的SDK包,开发者可以自由动态生成SDK包来适应不同的需求;

// 封装消息框模块
SDK.Dialog = {};
SDK.Dialog.Message = function(message) {
alert(message);
};

// 封装确认框模块
SDK.Dialog.Confirm = function(message) {
return confirm(message);
};

依赖注入

前端SDK中的不同模块之间可能会有依赖关系,可以通过依赖注入的方式实现依赖关系管理

// 声明依赖模块
SDK.Dialog = {};
SDK.Dialog.Message = function(message) {
alert(message);
};

SDK.Dialog.Confirm = function(message) {
return confirm(message);
};

// 依赖模块
SDK.Action = function(dialog) {
this.dialog = dialog;
}

// 注入依赖模块
var action = new SDK.Action(SDK.Dialog);
action.dialog.Message("Hello World");
  • 使用封装的SDK SDK的引用
// 在HTML页面中引入SDK库
<script type="text/javascript" src="sdk.js"></script>
    • API使用
// 调用SDK中的接口函数来实现相应功能
<button onclick="SDK.Dialog.Message('Hello World!')">
点我显示消息框
</button>

<button onclick="SDK.Dialog.Confirm('确定要删除吗?')">
点我显示确认框
</button>
    • 模块使用
// 通过依赖注入的方式使用SDK模块
var dialog = new SDK.Dialog();
var action = new SDK.Action(dialog);
action.ShowMessage('Hello World');



作者:FE杂志社
链接:https://juejin.cn/post/7304975276445057060

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表