0 前言
本文主要介紹如何基于JavaScript來開發SDK,任何基于JS的場景都可以用類似的思路來解決,無論是移動端H5還是服務端純NodeJS。文中會提及一些設計原則以及實作技巧,并結合
嶽鷹全景監控平台SDK 這個實際案例來展示如何應用它們。
1 SDK是什麼
SDK全稱是“Software Development Kit”,直譯就是軟體開發工具集。說的再通俗點就是一個面向開發者,針對特定領域的軟體包。比如 Java SDK(JDK),就是一個Java領域的軟體包。基于它,開發人員就可以快速建構自己的Java應用。比較規範的SDK一般都會包含若幹的API、開發工具集和說明文檔。
JS-SDK也無外于此,不過鑒于JS語言本身的特性,基于Ta封裝的SDK更多常見于UI元件庫、統計分析、web服務接口封裝、前端穩定性和性能監控等場景。上一小節提到的
SDK 即屬于前端穩定性和性能監控這一領域範疇的SDK。
2 設計原則
如何設計SDK,其實更多取決于你的場景,或者SDK最終的用途。比如實作一個給網頁調用的SDK與用于服務端的SDK就有明顯的差異,但這之間确實存在着一些共通的原則,或者方法論:
- 最小可用性原則,即用最少的代碼,如無必要勿增實體
- 最少依賴原則,即最低限度的外部依賴,如無必要勿增依賴
進一步闡述,即我們打造的SDK要符合以下的要求
2.1 滿足功能需求
SDK一般都是偏于面向某個領域,是以,同時在設計和實作的時候明确職責和邊界很重要,同時還應該足夠精簡,專注領域内的業務。
2.2 足夠穩定
- 絕不能導緻宿主應用崩潰,這是最基礎也是最嚴格的要求
- 較好的性能,比如SDK體積應盡量小,運作速度盡量快
- 可測試,保障每一次變更
- 向後相容,不輕易出現 Breakchange
2.3 少依賴,易擴充
- 最小程度的第三方依賴,盡可能自行實作,确實無法避免則最小化引入
- 插件化,最大限度支援擴充
- Hook機制,滿足個性化訴求
3 如何實作
下面我們将通過剖析 嶽鷹前端監控SDK 的設計過程,來看看上述的設計原則是如何應用到實際的開發過程中的。
3.1 明職責,定邊界
前面章節提到, 嶽鷹前端監控SDK 是前端穩定性和性能監控的SDK,主要面向前端H5領域。是以,稍加分析即可得出以下結論
- 前端領域,穩定性方面主要的關注點
- JS異常
- 資源加載異常
- API請求異常
- 白屏異常
- 性能方面,核心的關注點
- 白屏時間
- 可互動時間(TTI)
- 首屏時間
- FP / FMP / FCP 等
上述監控内容實際上都相對獨立,是以我們可以把Ta們橫向劃分為如下幾大部分:
明确了SDK的邊界以及各部分的職責,結合前端監控的特性,我們可以開始設計SDK的整體架構了。
3.2 築架構,夯基礎
俗話說千裡之行始于足下,是以築牢基礎十分重要。總得來說,我們需要做好下面幾點
-
首先确定SDK的引用形式
SDK整體而言是一個大子產品,前端子產品有多種表現形式:ES Module、CommonJS、AMD/CMD/UMD,而在引用方面則大體分 CDN和 NPM兩種。即無論我們實作的是哪種形式的子產品,最終都是通過CDN或者NPM的方式提供給使用者引用。
import wpkReporter from 'wpkReporter'
// CommonJS
const wpkReporter = require('wpkReporter')
// AMD,requireJS引用
require.config({
paths: {
"wpk": "https://g.alicdn.com/woodpeckerx/jssdk/wpkReporter.js",
}
})
require(['wpk', 'test'], function (wpk) {
// do your business
})
乍看有點眼花,但事實上今時今日的前端工程領域,已有很多利器可以幫助我們達到目的。比如 webpack,通過簡單的配置就可以建構出一個UMD的bundle。
module.exports = {
output: {
filename: '[name].js',
path: `${__dirname}/dist`,
globalObject: 'this',
library: '[name]',
libraryTarget: 'umd'
}
}
綜上,我們可以通過 webpack将 SDK建構為一個UMD bundle,這樣可以自動适配所有形式的子產品。同時我們也将同時提供 CDN和 NPM兩種引用方式,給使用者更多選擇。
-
确定SDK的版本管理機制
現有較成熟的版本管理機制當屬 語義化版本号 ,表現形式為 {主版本}.{次版本}.{更新檔版本},簡單易記好管理。
一般重大的變更才會觸發主版本号的更替,而且很可能新舊版本不相容。次版本主要對應新特性或者較大的調整,是以也有可能出現breakchange。其他小的優化或bugfix就基本都是在更新檔版本号展現。
看到此處,是否有點似曾相識的感覺?沒錯,所有NPM子產品都遵循語義化版本規範,是以結合第一點,我們可以将SDK初始化為一個NPM子產品,結合webpack的能力就可以實作基礎的版本管理及子產品建構。
-
确定SDK的基礎接口
接口是SDK和使用者溝通的橋梁,每一個接口對應着一個獨立的SDK功能,并且有明确的輸入和輸出。我們可以先來看看嶽鷹前端監控SDK的核心接口有哪些?
wpk.report(logData)
wpk.reportJSError(error)
wpk.reportAPIError(apiData)
// 配置變更
wpk.setConfig(data)
// SDK診斷
wpk.diagnose()
// 添加插件
wpk.addPlugin(plugin)
總結接口的設計原則,如下
-
職責單一
一個接口隻做一件事情
-
命名簡單清晰,參數盡量少但可擴充
好的接口命名就是最好的注釋,一看即明其用處
參數盡可能适用 Object封裝
- 做好參數校驗和邏輯保護
3.3 領域分析,子產品劃分
定邊界的時候,我們已經清楚劃分了SDK的幾個關鍵的部分:全局異常、API異常、頁面性能和白屏,實際上監控SDK通常也會内置對頁面流量的監控,以友善使用者對異常的影響面做出評估。這幾個核心的關鍵組成部分,每一塊都對應一個專業的領域,是以對應到SDK也是每一個獨立的子產品。
除了這些核心的偏領域的子產品,SDK還需要有更基礎的與領域無關的子產品,包括SDK核心(構造方法、插件機制、與下遊服務的互動、上報隊列機制、不同環境的管理等等)和工具類庫。
我們可以先看一下嶽鷹前端監控SDK最後的整體子產品劃分:
- SDK底層提供基礎的能力,包括上面提到的核心、插件機制的實作、工具類庫以及暴露給使用者的基礎API
- 可以看到,我們前面提到的所有子產品都以插件的形式存在,即各領域的功能都各自松散的做實作,這樣使得底層能力更具通用性,同時擴充能力也更強,使用者甚至也可以封裝自己的插件。
- Biz部分更多是對于不同宿主環境的多入口适配,目前支援浏覽器、Weex以及NodeJS。
3.4 測試覆寫,線上無憂
SDK是一個基礎服務,相對于前台業務而言可能更底層些。其影響面跟應用的範圍是正比的關系,更多的使用者意味着更大的責任。是以SDK的品質保障也是很重要的一個環節。
嶽鷹前端監控SDK的品質保障政策很簡單,隻有兩條
- 核心接口100%的單元測試覆寫率
- 釋出卡點:再小的版本釋出也需要走內建測試回歸
事實上,除了核心接口,工具類庫的所有功能我們都實作了 100%的單元測試覆寫,我們采用的前端測試工具是輕量好用的 Jest 。
test('isError: real error', function () {
var err = new Error('this is an error')
expect(util.isError(err)).toBeTruthy()
})
3.5 細節打磨,極緻體驗
- 快捷引入
- 極盡所能提高使用者引用的效率
- 一行代碼,快速引入,享用監控全家桶功能
<script>
!(function(c,i,e,b){var h=i.createElement("script");var f=i.getElementsByTagName("script")[0];h.type="text/javascript";h.crossorigin=true;h.onload=function(){c[b]||(c[b]=new c.wpkReporter({bid:"dta_1_203933078"}));c[b].installAll()};f.parentNode.insertBefore(h,f);h.src=e})(window,document,"https://g.alicdn.com/woodpeckerx/jssdk/wpkReporter.js","__wpk");
</script>
- 動态采樣
- 即通過雲端下發資料采樣率的方式,控制用戶端上報資料的頻率
- 更好的保護監控下遊
- 自我診斷
- 除了接口,SDK整體對使用者而言就是一個黑盒,是以使用者在遇到問題時很容易蒙圈 (如:為啥沒有上報資料)
- SDK可以提供一個自我診斷的接口,快速排除基礎問題
- 比如,SDK是否已正常初始化、關鍵參數是否正常設定等
- 增加調試模式,輸出更詳細的過程日志,友善定位問題
- 漸進式的指引文檔
- 圖文并茂,循序漸進
- 入門,一步步引導使用者初識SDK,領略概貌,學會基本的使用
- 進階,安利SDK的深度用法,幫助使用者更好的使用SDK
4 結語
實際在SDK的設計和開發過程中,要處理的問題還遠不止本文所述的内容,比如 NPM子產品開發時本地如何引用,建構的bundle大小如何調優等等。不過還是希望閱完此文,對你有所啟發。同時文中若有不對之處,還望不吝賜教。
通路