扩展egret cmd的自定义命令 和 自动写入default.res.json文件

版本声明

本文中使用的5.2.33引擎版本

大体思路

  1. 由于每次更新图集都要手动把资源文件拖一次,为了简化这个部分完成了MyEmitResConfigFilePlugin插件,原来的其实也是可以用的,但是图集的 png 文件也会在里面,而我们手动拖过去是没有的。
    原来的
    在这里插入图片描述
    手动托的在这里插入图片描述
  2. 这个可以使用 egret build 命令运行,但是我每次只更新图集,不想要等那么长时间的 build,于是想办法扩展了命令 egret build res,执行上面的插件

具体实现

重写EmitResConfigFilePlugin

在刚准备重写的时候是有点懵的,因为他原始的结构非常简单,
只实现了plugins.Command 和一个构造,有点无从下手,于是写下了一个这样的类。
export class MyEmitResConfigFilePlugin extends EmitResConfigFilePlugin {
    async onFile(file: plugins.File): Promise<plugins.File | null> {
        super.onFile(file);
    }
    
    async onFinish(pluginContext?: plugins.CommandContext): Promise<void> {
        console.log(this);
        super.onFinish(pluginContext);
    }
    
}
其中两个方法是 plugins.Command 接口中声明的。
/**
     * 构建管线命令
     */
    interface Command {

        /**
         * 项目中的每个文件都会执行此函数,返回 file 表示保留此文件,返回 null 表示将此文件从构建管线中删除,即不会发布
         */
        onFile?(file: File): Promise<File | null>

        /**
         * 项目中所有文件均执行完后,最终会执行此函数。
         * 这个函数主要被用于创建新文件
         */
        onFinish?(pluginContext?: CommandContext): Promise<void>

        [options: string]: any;
    }
运行后的打印:发现里面是有资源的一些结构信息的
TestEmitResConfigFilePlugun {
  options:
   { output: 'resource/default.res.json',
     typeSelector: [Function: typeSelector],
     nameSelector: [Function: nameSelector],
     groupSelector: [Function: groupSelector] },
  config:
   { alias: {},
     groups: {},
     resources:
      { default_thm_json: [Object],
        description_json: [Object],
        bg_jpg: [Object],
        by_bg_mp3: [Object],
        egret_icon_png: [Object],
        .....}},
  fileSystem:
   FileSystem {
     root:
      { default_thm_json: [Object],
        description_json: [Object],
        bg_jpg: [Object],
        lobby_json: [Object],
        ......},
     rootPath: 'resource' },
  remoteConfig: { alias: {}, groups: {}, resources: {} },
  remoteFileSystem: FileSystem { root: {}, rootPath: 'resource' },
  remoteRoot: '' }
里面还是有很多东西没有声明出来的,
那我们就直接给他声明出来好了,方便后面的操作,
于是api.d.ts 中的 EmitResConfigFilePlugin 变成了这样:
/** 
 * 生成 res.json 文件或者 res.js 文件
 */
export class EmitResConfigFilePlugin implements plugins.Command {

    protected config: { alias: {}, groups: {}, resources: { [key: string]: {url: string, type: string, name: string}} };
    protected fileSystem: { root: {}, rootPath: string };
    protected remoteConfig: { alias: {}, groups: {}, resources: { [key: string]: {url: string, type: string, name: string}} };
    protected remoteFileSystem: { root: {}, rootPath: string };
    protected remoteRoot: string;

    constructor(options: EmitResConfigFilePluginOptions)

    onFile(file: plugins.File);
    onFinish(pluginContext?: plugins.CommandContext);

}
然后我们就可以进行自己想要的剔除图集png的操作了,
这里是在 onFinish() 方法中实现的。

通过上面的 console.log(this),我们知道了资源信息在
this.config.resources 和 this.fileSystem.root 中
那我们把这两个中的剔除就好了。
这里把 this.remoteConfig.resources 和 this.remoteFileSystem.root 也进行了检查

上代码:
async onFinish(pluginContext?: plugins.CommandContext): Promise<void> {
    // 需要移除的
    let needRemoveArr = [];
    // console.log(this.config)
    let setSubkeys = (resources, root) => {
        for (let key in resources) {
            let item = resources[key];
            if (item.type == "sheet") {
                // 读取json文件
                let frames = (readFileSyncJson(root + item.url) as { file: string, frames: {} }).frames;
                if (frames) {
                    needRemoveArr.push(item);
                    let keys: string[] = [];
                    // key为图片名称
                    for (let key in frames) {
                        keys.push(key);
                    }
                    // 写入二级key
                    item.subkeys = keys.join(",");
                }
                // 防止之前的类型转换出错
                else if (item.type == "sheet") {
                    item.type = "json";
                }
            }
        }
    }
    
    // 移除png
    let reomveSheetPngFile = (resources, root) => {
        for (let k in needRemoveArr) {
            let name: string = needRemoveArr[k].name;
            let pngName = name.replace(/_json/, '_png');
            delete resources[pngName];
            delete root[pngName];
        }
    }

    let outputDir = pluginContext ? pluginContext.outputDir : "";
    setSubkeys(this.config.resources, outputDir + "/" + this.fileSystem.rootPath + "/");
    reomveSheetPngFile(this.config.resources, this.fileSystem.root);
    needRemoveArr.length = 0;

    setSubkeys(this.remoteConfig.resources, this.remoteRoot + "/" + this.remoteFileSystem.rootPath + "/");
    reomveSheetPngFile(this.remoteConfig.resources, this.remoteFileSystem.root);
    super.onFinish(pluginContext);
}
其中用到了读取文件 readFileSyncJson() 方法,这是自己封装的,
自己新建一个类,这里的名为:fileUtil.ts
import * as fs from 'fs';
import * as path from 'path';

export function readFileSyncJson(filePath: string) {
    let text = readFileSyncText(filePath);
    return text ? JSON.parse(text) : undefined;
}
最后把这个类在 config.ts 中替换掉原来的 EmitResConfigFilePlugin,
并把 typeSelector 方法按照自己的需要修改返回类型就完成了。
typeSelector: (path) => {
    const ext = path.substr(path.lastIndexOf(".") + 1);
    const typeMap = {
        "jpg": "image",
        "png": "image",
        "webp": "image",
        "json": "json",
        "fnt": "font",
        "pvr": "pvr",
        "mp3": "sound",
        "zip": "zip",
        "sheet": "sheet",
        "exml": "text",
        "txt": "text",
        "dbbin": "bin",
    }
    let type = typeMap[ext];
    if (type == "json") {
        if (type.indexOf('_tex') == -1) {
            type = "sheet";
        } else if (path.indexOf("movieclip") >= 0) {
            type = "movieclip";
        }
    }
    return type;
}

其中 onFile 和 onFinish 两个方法中都要用 super 调用父类的实现。同时我们可以在onFile() 中去对是否写入进行筛选。

async onFile(file: plugins.File) {
    if (file.path.indexOf('resource\\asset') == -1) {
            return null;
    }
    super.onFile(file);
    return file;
}

扩展命令

经过上面的操作就可以在 egret build 命令中执行了,但是如果项目大的话每次
build 需要的时间也是很久的,在官方论坛中看到 egret 的命令是用 nood.js 实现的,
于是就想试着打印一下,看看能不能获取到执行的命令,最后找到了两地方都可以拿到
分别是:global['egret'].args,global.process.argv,可以打印出来自己看下

在这里插入图片描述
在这里插入图片描述

于是就根据后面拿到的去做自己想要的处理,这里使用的 
global['egret'].args.commands[1] 获取指令
buildConfig: (params) => {
    const { target, command, projectName, version } = params;
    if (command == 'build') {
        const com = global['egret'].args.commands[1];
        const outputDir = '.';

        if (com == 'res') {
            return {
                outputDir: '',
                commands: [
                    new TestEmitResConfigFilePlugun({
                        output: "resource/default.res.json",
                        typeSelector: config.typeSelector,
                        nameSelector: p => path.basename(p).replace(/\./gi, "_"),
                        groupSelector: p => ''
                    }),
                ]
            }
        }

        return {
            outputDir,
            commands: [
                new ExmlPlugin('debug'), // 非 EUI 项目关闭此设置
                new IncrementCompilePlugin(),

                new TestEmitResConfigFilePlugun({
                    output: "resource/default.res.json",
                    typeSelector: config.typeSelector,
                    nameSelector: p => path.basename(p).replace(/\./gi, "_"),
                    groupSelector: p => ''
                }),
            ]
        }
}

大家可以根据这个扩展自己的订制命令了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值