跨端开发
@cloudbase/js-sdk 只支持常规 Web 应用(即浏览器环境)的开发,不兼容其他类 Web 平台,比如微信小程序、快应用、Cocos 等。虽然这些平台大多支持 JavaScript 运行环境,但在网络请求、本地存储、平台标识等特性上与浏览器环境有明显差异。针对这些差异特性,@cloudbase/js-sdk 提供一套完整的适配扩展方案,遵循此方案规范可开发对应平台的适配器,然后搭配 @cloudbase/js-sdk 和适配器实现平台的兼容性。
#
适配规范开发适配器之前需要安装官方提供的接口声明模块@cloudbase/adapter-interface
:
# npmnpm i @cloudbase/adapter-interface# yarnyarn add @cloudbase/adapter-interface
适配器模块需要导出一个adapter
对象:
const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: '平台名称'};
export adapter;export default adapter;
必须包含以下三个字段:
runtime
:string
,平台的名称,用于标记平台唯一性;isMatch
:Function
,判断当前运行环境是否为平台,返回boolean
值;genAdapter
:Function
,创建adapter
实体。
#
runtimeruntime
用于标记平台的唯一性,建议尽量以平台的英文名称或简写命名,比如百度小程序baidu_miniapp
、QQ 小程序qq_miniapp
等等。
#
isMatchisMatch
函数用于判断当前运行环境是否与适配器匹配,通常是通过判断平台特有的一些全局变量、API 等。比如以下代码是判断运行环境是否为 Cocos 原生平台:
function isMatch(): boolean { if (typeof cc === "undefined") { return false; } if (typeof WebSocket === "undefined") { return false; } if (typeof XMLHttpRequest === "undefined") { return false; }
if (!cc.game) { return false; } if (typeof cc.game.on !== "function") { return false; } if (!cc.game.EVENT_HIDE) { return false; } if (!cc.game.EVENT_SHOW) { return false; }
if (!cc.sys) { return false; } if (!cc.sys.isNative) { return false; }
return true;}
#
genAdaptergenAdapter
函数返回适配器的实体对象,结构如下:
interface SDKAdapterInterface { // 全局根变量,浏览器环境为window root: any; // WebSocket类 wsClass: WebSocketContructor; // request类 reqClass: SDKRequestConstructor; // 无localstorage时persistence=local降级为none localStorage?: StorageInterface; // 无sessionStorage时persistence=session降级为none sessionStorage?: StorageInterface; // storage模式首选,优先级高于persistence primaryStorage?: StorageType; // 获取平台唯一应用标识的api getAppSign?(): string;}
#
示例import { AbstractSDKRequest, IRequestOptions, IUploadRequestOptions, StorageInterface, WebSocketInterface, WebSocketContructor, SDKAdapterInterface, StorageType, formatUrl} from "@cloudbase/adapter-interface";
// isMatch函数判断当前平台是否匹配function isMatch(): boolean { // ... return true;}
// Request类为平台特有的网络请求,必须实现post/upload/download三个public接口export class Request extends AbstractSDKRequest { // 实现post接口 public post(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现upload接口 public upload(options: IUploadRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现download接口 public download(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); }}// Storage为平台特有的本地存储,必须实现setItem/getItem/removeItem/clear四个接口export const Storage: StorageInterface = { setItem(key: string, value: any) { // ... }, getItem(key: string): any { // ... }, removeItem(key: string) { // ... }, clear() { // ... }};// WebSocket为平台特有的WebSocket,与HTML5标准规范一致export class WebSocket { constructor(url: string, options: object = {}) { const socketTask: WebSocketInterface = { set onopen(cb) { // ... }, set onmessage(cb) { // ... }, set onclose(cb) { // ... }, set onerror(cb) { // ... }, send: (data) => { // ... }, close: (code?: number, reason?: string) => { // ... }, get readyState() { // ... return readyState; }, CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3 }; return socketTask; }}
// genAdapter函数创建adapter实体function genAdapter() { const adapter: SDKAdapterInterface = { // root对象为全局根对象,没有则填空对象{} root: window, reqClass: Request, wsClass: WebSocket as WebSocketContructor, localStorage: Storage, // 首先缓存存放策略,建议始终保持localstorage primaryStorage: StorageType.local, // sessionStorage为可选项,如果平台不支持可不填 sessionStorage: sessionStorage }; return adapter;}
// 三者缺一不可const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: "平台名称"};
export default adapter;
#
接入流程#
第 1 步:安装并引入适配器安装 @cloudbase/js-sdk 和所需平台的适配器,比如 QQ 小游戏平台:
# 安装 @cloudbase/js-sdknpm i @cloudbase/js-sdk# 安装 QQ 小游戏适配器npm i cloudbase-adapter-qq_game
然后在业务代码中将引入适配器:
import cloudbase from "@cloudbase/js-sdk";import adapter from "cloudbase-adapter-qq_game";
cloudbase.useAdapters(adapter);
#
第 2 步:配置安全应用来源云开发需验证请求来源的合法性,常规 Web 通过验证安全域名,而由于上文提到的诸多类 Web 环境并没有域名的概念,所以需要借助安全应用凭证区分请求来源是否合法。
登录云开发 CloudBase 控制台,在安全配置页面中的移动应用安全来源一栏:
点击“添加应用”按钮,输入应用标识:
caution
应用标识必须是能够标记应用唯一性的信息,比如微信小程序的appId
、移动应用的包名等。
添加成功后会创建一个安全应用的信息,如下图所示:
#
第 3 步:初始化云开发在业务代码中初始化云开发时将第 2 步配置的安全应用信息作为参数传递给 init
方法:
import cloudbase from '@cloudbase/js-sdk';import adapter from 'cloudbase-adapter-qq_game';
cloudbase.useAdapters(adapter);
cloudbase.init({ env: '环境ID', appSign: '应用标识', appSecret: { appAccessKeyId: '应用凭证版本号' appAccessKey: '应用凭证' }})
appSign
:string
,应用标识,对应上图中“应用标识”一栏;appSecret
:Object
,应用凭证信息,包括以下字段:appAccessKeyId
:string
,对应上图中“版本”一栏,同一个应用标识可以最多可以添加两个版本的凭证信息,以便区分开发和生产环境;appAccessKey
:string
,对应上图中“操作”一栏点击“获取凭证”之后获取到的信息。
tip
appAccessKey
和appAccessKeyId
必须一一对应。
#
第 4 步:编写业务代码经过以上准备工作之后便可以编写自身的业务代码。
#
已有适配器目前已有的适配器可以在云开发社区官网中查看。
tip
所有适配器均来自社区贡献,欢迎更多开发者加入。
#
一套代码多端适配如果您需要将一套代码兼容多种平台,tcb-js-sdk 可以同时引入多个适配器,在运行时通过各适配器的isMatch
函数判断平台类型,然后引入对应的兼容逻辑。比如以下代码可以同时兼容 QQ 小游戏、 Cocos 原生和百度小游戏三种平台:
import cloudbase from '@cloudbase/js-sdk';import adapter as adapterOfQQGame from 'cloudbase-adapter-qq_game';import adapter as adapterOfCocosNative from 'cloudbase-adapter-cocos_native';import adapter as adapterOfBDGame from 'cloudbase-adapter-bd_game';
cloudbase.useAdapters([ adapterOfQQGame, adapterOfCocosNative, adapterOfBDGame]);