CocosCreator TypeScript项目引用第三方库的方法和问题记录

TypeScript对于习惯强类型语言(比如Unity C#)而又要写JavaScript项目(比如CocosCreator Egret)的程序员来说,确实提供了很大方便,而且对于一些由于弱类型语言导致的只能运行时检查的低级错误,使用TS都能很好的避免。

这次要记录的是使用TypeScript作为主开发语言的CocosCreator项目中引用第三方库的方法和问题,实测的是MessagePackprotobufjs和Photon这几个库。

首先是MessagePack,这个用了最无脑的npm包方式,虽然新版本的Creator(我写这篇博文的时候用的是v2.1.0)已经号称不支持npm方式引用第三方库(据说从1.6开始,http://forum.cocos.com/t/1-6-npm/49926),但实测直接以node npm方式在项目根目录下添加package.json并指定第三方库还是可以正常工作的,当然如论坛里官方人员说的,这样确实会带来某些弊端,比如依赖之类的,但毫无疑问npm管理第三方js库是最方便的。对于MsgPack,package.json可以直接手写如下:

{
    "name": "",
    "version": "",
    "dependencies": {
        "@types/msgpack-lite": "^0.1.6",
        "msgpack-lite": "^0.1.26"
    }
}

也可以npm install -S方式,这样完成后还会直接安装ts需要的.d接口定义,直接在Creator .ts里使用即可:

import * as msgpack from "msgpack-lite";

const { ccclass, property } = cc._decorator;

@ccclass
export default class Helloworld extends cc.Component {

    @property(cc.Label)
    label: cc.Label = null;

    @property
    text: string = 'hello';

    start() {
        // init logic
        this.label.string = this.text;
        const temp = msgpack.encode({ test: "asdasd" });
        console.log(">>>>", temp);
        const dtemp = msgpack.decode(temp);
        console.log("<<<<<", dtemp);
    }
}

下一个是Photon JS库,这个就没有npm包方式了,只有官网提供的Download SDK方式下载:https://www.photonengine.com/en-us/sdks#realtimejavascript,这个就要按照Creator目前官方推荐的方式引入了:https://docs.cocos.com/creator/manual/zh/scripting/plugin-scripts.html,由于不需要调试或读js源码,接口有ts定义,所以直接复制下载好的Photon JS库中的Photon-Javascript_SDK.min.js和Photon-Javascript_SDK.d.ts到Creator项目中,并且标记插件脚本即可:

由于这种方式,Creator会将插件脚本进行全局化处理,因此不用像MsgPack那样再做import,直接使用即可(实测VSCode这样基于ts定义的感知也可正常工作):

        this._photonLBC = new Photon.LoadBalancing.LoadBalancingClient(
            Photon.ConnectionProtocol.Ws,
            appId,
            ConstData.CLIENT_VER
        );

        this._photonLBC.onStateChange = (state: number) => {
            cc.log("LBC onStateChange: " + state);

            const sceneMain = cc.find("Canvas").getComponent(SceneMain);

            const LBCState = Photon.LoadBalancing.LoadBalancingClient.State;

            switch (state) {
                case LBCState.ConnectedToNameServer:
                    sceneMain.outputLog("已连接NameServer!");
                    break;
                case LBCState.ConnectedToMaster:
                    sceneMain.outputLog("已连接Master!");
                    break;
                case LBCState.JoinedLobby:
                    sceneMain.outputLog("已加入Lobby!");
                    break;
                case LBCState.Joined:
                    break;
                case LBCState.Disconnected:
                    sceneMain.outputLog("已断开连接!");
                    break;
                default:
                    cc.warn(`LBC state not handled: ${state}`);
                    break;
            }
        };

最后是Protobuf,这个在之前的js项目中也用到过了,而且百度下相关资料一大把,各种引入方式,各种使用方式,proto生成js文件的,直接使用proto动态解析的,并且刚才给出的官方文档里,也以protobufjs为例进行了说明:

如果插件还依赖于其它插件,也需要把多个插件合并为单个 js 文件
以 protobuf.js 为例,这个库还依赖于 bytebuffer.js,但是插件作者并没有提供整合好的独立运行版本。我们可以先下载到这两个库各自编译后的两个文件 protobuf.js 和 bytebuffer.js,然后使用文本编辑器或类似 cat 这样的命令行工具将这两个脚本拼合成一个新的脚本 protobuf_all.js。然后就能在 Creator 中直接使用这个 protobuf_all.js 了。

现在新release的6.x已经不需要再手动做这个整合操作了,直接将pbjs作者提供好的protobuf.min.js和index.d.ts改名为protobuf.d.ts一起复制进项目,然后如法炮制设置插件脚本,这样都设置好以后,会发现并没有像刚才Photon那样开箱即用,而会收到这么个错误:

‘protobuf’ refers to a UMD global, but the current file is a module. Consider adding an import instead.ts(2686)

一通查之后,发现问题在于protobuf.d.ts中的namespace声明方式,其实直接无视这个lint错误,在编译到js状态时运行还是不会出错的,但这样一来代码里一直有错误提示,二来ts的大优势,代码感知protobuf相关的就用不了了,所以解决方法是修改下.d.ts,在最外层像Photon库一样使用declare module方式声明:

// export as namespace protobuf;
declare module protobuf {

/**
 * Provides common type definitions.
 * Can also be used to provide additional google types or your own custom types.
 * @param name Short name as in `google/protobuf/[name].proto` or full file name
 * @param json JSON definition within `google.protobuf` if a short name, otherwise the file's root definition
 */
export function common(name: string, json: { [k: string]: any }): void;

export namespace common {

    /** Properties of a google.protobuf.Any message. */
    interface IAny {
        typeUrl?: string;
        bytes?: Uint8Array;
    }

...

/**
 * An allocator as used by {@link util.pool}.
 * @param size Buffer size
 * @returns Buffer
 */
type PoolAllocator = (size: number) => Uint8Array;

/**
 * A slicer as used by {@link util.pool}.
 * @param start Start offset
 * @param end End offset
 * @returns Buffer slice
 */
type PoolSlicer = (this: Uint8Array, start: number, end: number) => Uint8Array;

}

这样修改以后,ts使用时就不会报错了,也可以正常感知protobufjs相关api了。

博主友情提示:

如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。