跨端开发
@cloudbase/js-sdk 只支持常规 Web 应用(即浏览器环境)的开发,不兼容其他类 Web 平台,比如微信小程序、快应用、Cocos 等。虽然这些平台大多支持 JavaScript 运行环境,但在网络请求、本地存储、平台标识等特性上与浏览器环境有明显差异。针对这些差异特性,@cloudbase/js-sdk 提供一套完整的适配扩展方案,遵循此方案规范可开发对应平台的适配器,然后搭配 @cloudbase/js-sdk 和适配器实现平台的兼容性。
适配规范
开发适配器之前需要安装官方提供的接口声明模块@cloudbase/adapter-interface
:
# npm
npm i @cloudbase/adapter-interface
# yarn
yarn add @cloudbase/adapter-interface
适配器模块需要导出一个adapter
对象:
const adapter = {
genAdapter,
isMatch,
// runtime标记平台唯一性
runtime: '平台名称'
};
export adapter;
export default adapter;
必须包含以下三个字段:
runtime
:string
,平台的名称,用于标记平台唯一性;isMatch
:Function
,判断当前运行环境是否为平台,返回boolean
值;genAdapter
:Function
,创建adapter
实体。
runtime
runtime
用于标记平台的唯一性,建议尽量以平台的英文名称或简写命名,比如百度小程序baidu_miniapp
、QQ 小程序qq_miniapp
等等。
isMatch
isMatch
函数用于判断当前运行环境是否与适配器匹配,通常是通过判断平台特有的一些全局变量、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;
}
genAdapter
genAdapter
函数返回适配器的实体对象,结构如下:
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-sdk
npm 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 控制台,在安全配置页面中的移动应用安全来源一栏:
点击“添加应用”按钮,输入应用标识:
应用标识必须是能够标记应用唯一性的信息,比如微信小程序的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
,对应上图中“操作”一栏点击“获取凭证”之后获取到的信息。
appAccessKey
和appAccessKeyId
必须一一对应。
第 4 步:编写业务代码
经过以上准备工作之后便可以编写自身的业务代码。
一套代码多端适配
如果您需要将一套代码兼容多种平台,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
]);