Skip to main content

Cross-Platform Development

@cloudbase/js-sdk only supports the development of conventional Web applications (i.e., browser environments) and is not compatible with other Web-like platforms, such as WeChat Mini Programs, Quick Apps, Cocos, etc. Although most of these platforms support a JavaScript runtime environment, they exhibit significant differences from browser environments in features like network requests, local storage, and platform identifiers. To address these differences, @cloudbase/js-sdk provides a complete adaptation extension solution. By following this solution's specifications, developers can create adapters for corresponding platforms, and then integrate @cloudbase/js-sdk with the adapters to achieve platform compatibility.

Adaptation Specifications

Before developing an adapter, you need to install the officially provided interface declaration module @cloudbase/adapter-interface:

# npm
npm i @cloudbase/adapter-interface
# yarn
yarn add @cloudbase/adapter-interface

The adapter module needs to export an adapter object:

const adapter = {
genAdapter,
isMatch,
// runtime marks the uniqueness of the platform
runtime: 'platform name'
};

export adapter;
export default adapter;

Must include the following three fields:

  • runtime: string, the name of the platform, used to uniquely identify the platform;
  • isMatch: Function, determines whether the current runtime environment is the platform and returns a boolean value;
  • genAdapter: Function, creates an adapter entity.

runtime

The runtimeis used to uniquely identify the platform. It is recommended to name it using the platform's English name or abbreviation, such asbaidu_miniappfor Baidu Mini Program,qq_miniapp` for QQ Mini Program, etc.

isMatch

The isMatch` function is used to determine whether the current runtime environment matches the adapter, typically by checking platform-specific global variables, APIs, etc. For example, the following code checks whether the runtime environment is the Cocos native platform:

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

The genAdapter` function returns the entity object of the adapter, with the following structure:

interface SDKAdapterInterface {
// Global root variable, in the browser environment, it is window
root: any;
// WebSocket class
wsClass: WebSocketContructor;
// request class
reqClass: SDKRequestConstructor;
// When localstorage is unavailable, persistence=local falls back to none
localStorage?: StorageInterface;
// When sessionStorage is unavailable, persistence=session falls back to none
sessionStorage?: StorageInterface;
// storage mode is preferred and takes precedence over persistence
primaryStorage?: StorageType;
// api to obtain the unique application identifier for the platform
getAppSign?(): string;
}

Example

import {
AbstractSDKRequest,
IRequestOptions,
IUploadRequestOptions,
StorageInterface,
WebSocketInterface,
WebSocketContructor,
SDKAdapterInterface,
StorageType,
formatUrl,
} from "@cloudbase/adapter-interface";

// The isMatch function determines whether the current platform matches
function isMatch(): boolean {
// ...
return true;
}

// The Request class is a platform-specific network request that must implement three public interfaces: post/upload/download
export class Request extends AbstractSDKRequest {
// Implement the post interface
public post(options: IRequestOptions) {
return new Promise((resolve) => {
// ...
resolve();
});
}
// Implement the upload interface
public upload(options: IUploadRequestOptions) {
return new Promise((resolve) => {
// ...
resolve();
});
}
// Implement the download interface
public download(options: IRequestOptions) {
return new Promise((resolve) => {
// ...
resolve();
});
}
}
// Storage is a platform-specific local storage that must implement four interfaces: setItem/getItem/removeItem/clear
export const Storage: StorageInterface = {
setItem(key: string, value: any) {
// ...
},
getItem(key: string): any {
// ...
},
removeItem(key: string) {
// ...
},
clear() {
// ...
},
};
// WebSocket is a platform-specific WebSocket that conforms to the HTML5 standard specification
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;
}
}

// The genAdapter function creates an adapter entity
function genAdapter() {
const adapter: SDKAdapterInterface = {
// root is the global root object; initialize as an empty object {} if not present
root: window,
reqClass: Request,
wsClass: WebSocket as WebSocketContructor,
localStorage: Storage,
// First, for the cache storage strategy, it is recommended to always use localstorage
primaryStorage: StorageType.local,
// sessionStorage is optional and can be omitted if the platform does not support it
sessionStorage: sessionStorage,
};
return adapter;
}

// All three are indispensable
const adapter = {
genAdapter,
isMatch,
// runtime marks the uniqueness of the platform
runtime: "platform name",
};

export default adapter;

Access Process

Step 1: Install and import the adapter

Install @cloudbase/js-sdk and the adapter for the required platform, such as the QQ mini-game platform:

# Install @cloudbase/js-sdk
npm i @cloudbase/js-sdk
# Install the QQ Mini-Game Adapter
npm i cloudbase-adapter-qq_game

Then, introduce the adapter in the business code:

import cloudbase from "@cloudbase/js-sdk";
import adapter from "cloudbase-adapter-qq_game";

cloudbase.useAdapters(adapter);

Step 2: Configure Security Application Source

CloudBase requires verification of request source legitimacy. Conventional Web environments use secure domains for verification, but as mentioned above, many Web-like environments lack the concept of domains. Therefore, secure application credentials are needed to distinguish legitimate request sources.

Log in to the CloudBase console, navigate to the Security Sources page, and in the Mobile Application Security Sources section, click the "Add Application" button to enter the application identifier.

tip

The application identifier must be information that uniquely identifies the application, such as the appId for WeChat Mini Programs, the package name for mobile applications, etc.

Upon successful addition, a security application record will be created, as shown in the figure below:

Step 3: Initialize CloudBase

When initializing CloudBase in the business code, pass the security application information configured in Step 2 as a parameter to the init method:

import cloudbase from '@cloudbase/js-sdk';
import adapter from 'cloudbase-adapter-qq_game';

cloudbase.useAdapters(adapter);

cloudbase.init({
env: 'Environment ID',
appSign: 'Application Identifier',
appSecret: {
appAccessKeyId: 'Application Credential Version Number'
appAccessKey: 'Application Credential'
}
})
  • appSign: string, Application Identifier, corresponding to the "Application Identifier" field in the above figure;
  • appSecret: Object, application credential information, including the following fields:
    • appAccessKeyId: string, corresponding to the "Version" field in the above figure. The same application identifier can have up to two versions of credential information to distinguish between development and production environments;
    • appAccessKey: string, corresponds to the information obtained after clicking "Get Credentials" in the "Operations" column of the above figure.
tip

The appAccessKeyandappAccessKeyId` must correspond one-to-one.

Step 4: Write Business Code

After completing the above preparations, you can proceed to write your business code.

A Single Codebase for Multi-end Adaptation

If you need to make a single codebase compatible with multiple platforms, tcb-js-sdk can incorporate multiple adapters simultaneously. During runtime, it uses each adapter's isMatch function to determine the platform type and then loads the corresponding compatibility logic. For example, the following code can simultaneously support three platforms: QQ Mini Games, Cocos native, and Baidu Mini Games:

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
]);